Do you want a menu in your PyQt app?

A menu bar sits at the top of a window and holds the commands of your app: File, Edit, View, Help. In PyQt you build it from two classes, QMenu for the menu itself and QAction for every item inside it.

A menu is not a row of buttons. The user only sees the items when they open the menu, which keeps the window clean.

A menu is different from a layout of buttons. The menu is a list of commands, and the user only sees it when they click on it.

Pyqt has menu support. Almost every GUI app has a main menu at the top of the window. Adding a menu works slightly different than adding widgets.

pyqt menu

A menu can contain sub menus, they are usually something like (File, Edit, View, History, Help). Every menu has actions.

Pyqt menu example

The menu is created with:

menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')

Then actions are added to the file menu:

fileMenu.addAction(newAction)
fileMenu.addAction(openAction)
fileMenu.addAction(exitAction)

These actions must be defined beforehand:

# Create new action
newAction = QAction(QIcon('new.png'), '&New', self)
newAction.setShortcut('Ctrl+N')
newAction.setStatusTip('New document')
newAction.triggered.connect(self.newCall)

# Create new action
openAction = QAction(QIcon('open.png'), '&Open', self)
openAction.setShortcut('Ctrl+O')
openAction.setStatusTip('Open document')
openAction.triggered.connect(self.openCall)

# Create exit action
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.exitCall)

Complete code:

import sys
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QWidget, QPushButton, QAction
from PyQt5.QtCore import QSize
from PyQt5.QtGui import QIcon

class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)

self.setMinimumSize(QSize(300, 100))
self.setWindowTitle("PyQt menu example - pythonprogramminglanguage.com")

# Add button widget
pybutton = QPushButton('Pyqt', self)
pybutton.clicked.connect(self.clickMethod)
pybutton.resize(100,32)
pybutton.move(130, 30)
pybutton.setToolTip('This is a tooltip message.')

# Create new action
newAction = QAction(QIcon('new.png'), '&New', self)
newAction.setShortcut('Ctrl+N')
newAction.setStatusTip('New document')
newAction.triggered.connect(self.newCall)

# Create new action
openAction = QAction(QIcon('open.png'), '&Open', self)
openAction.setShortcut('Ctrl+O')
openAction.setStatusTip('Open document')
openAction.triggered.connect(self.openCall)

# Create exit action
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.exitCall)

# Create menu bar and add action
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(newAction)
fileMenu.addAction(openAction)
fileMenu.addAction(exitAction)

def openCall(self):
print('Open')

def newCall(self):
print('New')

def exitCall(self):
print('Exit app')

def clickMethod(self):
print('PyQt')

if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mainWin = MainWindow()
mainWin.show()
sys.exit( app.exec_() )

How the pieces fit

  • menuBar = self.menuBar() gets the menu bar of the window.
  • fileMenu = menuBar.addMenu('&File') adds a menu with a label. The & before the letter sets the keyboard shortcut.
  • action = QtWidgets.QAction('Open', self) creates one item.
  • action.triggered.connect(self.method) connects it to your function.
  • fileMenu.addAction(action) puts the item in the menu.
  • action.setShortcut('Ctrl+O') gives the item a shortcut.

Menus can be nested. Add a submenu with menu.addMenu('More').

How the pieces fit

  • menuBar = self.menuBar() gets the menu bar of the window.
  • fileMenu = menuBar.addMenu('&File') adds a menu with a label. The & before the letter sets the keyboard shortcut for the menu itself.
  • action = QtWidgets.QAction('Open', self) creates one item.
  • action.triggered.connect(self.open_file) connects it to your function.
  • fileMenu.addAction(action) puts the item in the menu.
  • action.setShortcut('Ctrl+O') gives the item a shortcut.
  • action.setEnabled(False) greys the item out, for a Paste that only works after a copy.
  • menu.addMenu('More') adds a submenu.

Use a separator with fileMenu.addSeparator() between groups of items, for example Save above and Quit below.

Want more practice on this? Practise this on PyChallenge, there are short browser exercises you can run right after reading.