user144153
user144153

Reputation: 858

Missing menuBar in PyQt5

I've been developing a GUI using PyQt5 and wanted to include a menu bar. When I went to code this feature, however, my menu wouldn't appear. Figuring my understanding on how to implement menu bars in PyQt5 was off, I looked for a pre-existing example online. With some tweaking I developed the following test case:

import sys
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QMainWindow, QMenuBar, QAction, qApp

class Example(QMainWindow):

    def __init__(self):
        super().__init__()

        exitAction = QAction(QIcon('exit.png'), '&Exit', self)
        exitAction.triggered.connect(qApp.quit)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&Testmenu')
        fileMenu.addAction(exitAction)

        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

When I run this, however, Testmenu is nowhere to be found.

I have also tried creating the menu bar (and the rest of my GUI layout) in QTCreator before converting the .ui file to an importable .py using pyuic5. I thought this would eliminate some programming mistake on my end, but the menubar still won't show. Any thoughts?

Edit:

Im running this code using Python 3.5 (Anaconda 4.1) from within a Jupyter notebook, version 4.1. I'm also using a Macbook running os 10.1l, PyQt 5.7 and Qt version 5.7.0.

I've realized that the menu bar will become responsive if I click off the application window and then click back onto the window - effectively unfocusing and the focusing the application. Armed with this information I realized that I am not the first to notice this problem (see https://github.com/robotology/yarp/issues/457). Unfortunately, I'm still not sure how to resolve the issue.

Upvotes: 12

Views: 14446

Answers (6)

pete
pete

Reputation: 41

Under MacOS, an application menu appears at the top of the screen. I managed to get the Quit menu option to appear in the above example by prepending the string "Quit" with a null character as follows:

close = QAction("\0Quit",self)
close.setShortcut("Ctrl+Q")
file.addAction(close)

It seems macOS somehow intercepts the menu items called "Quit" or "Exit". You can happily use "Close" or "Leave" without the workaround.

Upvotes: 1

Nija I Pillai
Nija I Pillai

Reputation: 1136

Menubar isn't visible in PyQt5

bar = self.menuBar()

bar.setNativeMenuBar(False)

file = bar.addMenu("File")

file.addAction("New")

NativeMenuBar property specifies whether or not the menubar should be used as a native menubar on platforms that support it. If this property is true, the menubar is used in the native menubar and is not in the window of its parent, if false the menubar remains in the window.

Sample program

import sys

from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication

from PyQt5.QtGui import QIcon


class Menu(QMainWindow):

    def __init__(self):
        super().__init__()
        self.initUI()


    def initUI(self):               

        exitAct = QAction(QIcon('exit.png'), ' &Quit', self)   

        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Exit application')
        exitAct.triggered.connect(qApp.quit)

        self.statusBar()

        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAct)

        bar = self.menuBar()
        file = bar.addMenu("Edit")
        file.addAction("New")

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Simple menu')    
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Menu()
    sys.exit(app.exec_())

Upvotes: 16

doosik71
doosik71

Reputation: 71

If your program is running on Ubuntu, you may find your menu bar on the top of the screen.

If you want to move menu bar to window's title bar, you can toggle the setting at "System setting / Appearance / Behavior / Show the menus for a window / In the window's title bar".

Upvotes: 6

hwiorn
hwiorn

Reputation: 136

It's not a Qt and PyQt5 Bug.

I think your code is zetcode pyqt5 menubar tutorial. I experienced the exact same problem on Mac OS.

First solution is a trick. Use ' &Exit' instead of '&Exit'. Insert a space at the beginning of '&Exit' like this:

...
# exitAction = QAction(QIcon('exit.png'), '&Exit', self) # Not shown
exitAction = QAction(QIcon('exit.png'), ' &Exit', self)
...

The system-wide menubar of macOS reserves keywords such as "Exit", "Quit", and etc. For the same reason, yurisnm's example code shows only the menu items except "Quit" on Mac OS. Actually "Quit" has TextHeuristicRole, so overrides "Quit " behavior in the Application menu. When you click "Quit python" in "Python" menu, it does not quit and just print "quit triggered".

If you must use that name in other menu(e.g. File, Edit), you need to change the action name like above or use QAction::setMenuRole(...) like this:

...
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
print(exitAction.menuRole()) # It prints "1". QAction::TextHeuristicRole
exitAction.setMenuRole(QAction.NoRole)
...

Please read the following, it will be help you.

Upvotes: 12

yurisnm
yurisnm

Reputation: 1640

Have you tried the most simple example in the following link tutorialspoint.

Here is the most simple example.

import sys

from PyQt5.QtWidgets import QHBoxLayout, QAction, QApplication, QMainWindow

class menudemo(QMainWindow):
    def __init__(self, parent = None):
        super(menudemo, self).__init__(parent)

        bar = self.menuBar()
        file = bar.addMenu("File")
        file.addAction("New")

        save = QAction("Save",self)
        save.setShortcut("Ctrl+S")
        file.addAction(save)

        edit = file.addMenu("Edit")
        edit.addAction("copy")
        edit.addAction("paste")

        quit = QAction("Quit",self)
        file.addAction(quit)
        file.triggered[QAction].connect(self.processtrigger)
        self.setWindowTitle("menu demo")

    def processtrigger(self, q):
        print(q.text()+" is triggered")


def main():
    app = QApplication(sys.argv)
    ex = menudemo()
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Upvotes: 0

try this:

menubar = QMenuBar()
self.setMenuBar(menubar)

instead of menubar = self.menuBar()

Upvotes: 0

Related Questions