7

I am attempting to add an item to the application menu-bar of a simple PyQt example. However, the following code does not seem to alter the menu-bar at all. The only item in the menu is "Python". Below is the bulk of the code, minus imports and instantiation.

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

        self.resize(250, 150)
        self.setWindowTitle('menubar')
        self.modal = False

        exit = QtGui.QAction( QtGui.QIcon('images/app_icon.png'), 'Exit', self )
        exit.setShortcut('Ctrl+Q')
        exit.setStatusTip('Exit application')
        self.connect(exit, QtCore.SIGNAL('triggered()'), QtCore.SLOT('close()'))

        menubar = self.menuBar()
        file = menubar.addMenu('File')
        file.addAction(exit)

I've also tried creating a new QMenuBar and using the setMenuBar() method to manually swap out the menu bar.

Any glaring mistakes in the above snippet?

JeremyFromEarth
  • 14,344
  • 4
  • 33
  • 47

4 Answers4

7

When using PyQt on a mac, the system will intercept certain commands contain the word 'Quit' or 'Exit' and remove them from your menubar because they exist elsewhere. if a menubar header has no items, it will not display, making it appear as if you haven't modified the menubar.

#exit = QtGui.QAction( 'Exit', self ) #this fails on my system
exit = QtGui.QAction( 'SomethingElse', self ) #this displays on my system
menubar = self.menuBar()
fileMenu = menubar.addMenu('&File')
fileMenu.addAction(exit)

Also, calling raise_() doesn't change the menubar on my mac. I have to manually select the window (by clicking else where then reclicking), if i use raise_(), to get the correct menubar to show for my pyqt app.

Also remember that mac menubars are displayed in the system menubar not in the window like on a Windows or Linux machine. This leads us to the other solution, as suggested by Levi501 and Swdev. That is to use a non-native menu that appears in the window like so:

menubar = self.menuBar()
menubar.setNativeMenuBar(False)

As someone who uses windows and linux alot, this makes alot more sense for my projects.

I found the 'Exit' information here: http://python.6.x6.nabble.com/addAction-to-menubar-td1916296.html

Greg
  • 1,549
  • 1
  • 20
  • 34
6

I know this question is old but, since I was stuck with the same problem, I found that because I was creating an action to quit the application and this action is reserved on OSX to the Application Menu, the File menu did not appear. As I created a new action on the same menu, it became available. This worked by using the same approach for other OS's:

self.menubar = self.menuBar()

This was created inside a QMainWindow object.

Hope this helps anyone!

tftdias
  • 153
  • 2
  • 9
  • Good to know it was useful @ChrisCalloway. – tftdias Apr 14 '14 at 14:38
  • Thanks for this! The important part is not about the `self.menuBar()` code, but the fact that I am testing to add Quit action. Adding another menu, displayed this – swdev Oct 05 '14 at 06:08
3

I don't have PyQt installed on this machine to test this out, but I think on a Mac the QMainWindow.menuBar() function does not return the application wide menu bar.

You might try creating a menubar like:

menubar = QtGui.MenuBar()

I'm basing this on the docs for the QMainWindow.menuBar() function here:

http://doc.qt.io/qt-4.8/qmainwindow.html#menuBar

You might also check out the section labeled QMenuBar on Mac OS X on this page:

http://doc.qt.io/qt-4.8/qmenubar.html#details

Hope that helps!

jesterjunk
  • 2,342
  • 22
  • 18
ryan_s
  • 7,826
  • 3
  • 27
  • 28
  • 2
    Another option, to put the menubar in the window itself is if sys.platform=="darwin": QtGui.qt_mac_set_native_menubar(False) – levis501 Nov 25 '13 at 00:19
  • I install PyQt4 using brew, and using this code still won't display my menu bar in unified mode. I can show the menubar to be inside application mainwindow, only by setting `self.menuBar.setNativeMenuBar(False)`. Any suggestion? – swdev Feb 20 '14 at 09:29
2

Correct. On MAC OS we need to use menubar like this:

self.menubar = QtGui.QMenuBar() 

And not like this:

self.menubar = QtGui.QMenuBar(MainWindow) 

(without the MainWindow parameter)

I suggest the best solution is using QTDesiner to build the UI layout then using pyside-uic tool to convert to a Python class on different platform. When I used the UI layout class compiled on Windows in MAC I got this issue. Solve this issue by simply recompiling the UI layout XML on MAC with the command pyside-uic AppMain.ui -o ui_AppMain.pyp

After I compare the compiled UI layout class between MAC and Windows the only difference is that on Max OS X new QMenuBar object is created without MainWindow parameter.

Wladimir Palant
  • 56,865
  • 12
  • 98
  • 126