1

I want a single menubar in my main window and be able to set the menus in the menubar from additional classes. Using the setMenuWidget command will overwrite the first menu option as shown in the code. In the classes where I set up the menu I think I may need to just set up a menu rather than a menubar, then set up the menubar in the main window.

This is what I would l like, which can be achieved by populating a single menubar in a class, though I am trying to avoid this method.

enter image description here

Instead only the second menu is show

enter image description here

import sys
from PyQt5.QtWidgets import QAction, QApplication, QMainWindow
from PyQt5 import QtCore, QtGui, QtWidgets

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

        bar = self.menuBar() # don't think I need a menubar here
        file_menu = bar.addMenu('menu1')
        one = QAction('one', self)
        two = QAction('two', self)
        file_menu.addAction(one)
        file_menu.addAction(two)


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

        bar = self.menuBar() # don't think I need a menubar here
        file_menu = bar.addMenu('menu2')
        one = QAction('one', self)
        two = QAction('two', self)
        file_menu.addAction(one)
        file_menu.addAction(two)


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

        #should a menubar be set up here?

        #For seting widgets in main window
        self.Tool_Bar0 = ToolBar0(self)
        self.setMenuWidget(self.Tool_Bar0)

        ###menu_bar0 is over written
        self.Tool_Bar1 = ToolBar1(self)
        #self.setMenuWidget(self.Tool_Bar1)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    # creating main window
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())
Kermit
  • 4,922
  • 4
  • 42
  • 74
  • Okay so from what I understand of this -- in pyqt you have only 1 Menubar but you can have multiple Menus within that. So what you want to Class is not the Menubar but the things that you add to the Menubar `self.FileMenu = self.MainMenu.addMenu('File')` as in this example what you would want to Class is the FileMenu and not the MainMenu which should be doable. Note you may have to create a generic routine the populates your MainMenu with these objects as it might be multi-step process – Dennis Jensen Aug 27 '19 at 13:02
  • Thanks Dennis, I can see that I need to set up the menus within the class then add to menubar in the main window though I cannot figure out how to do this – anthony crimin Aug 27 '19 at 13:43
  • Actually you could create the MenuBar as a self-contained class and simply instantiate it this takes setting up the MenuBar within your MainWindow function down to a one-liner and allows you to modularize this in case you wish to swap that out at some point in time or need to work on it specifically. I always sub-class my menu/tool bar in this fashion as it streamlines my MainWindow to its bare essentials. So basically 2 classes one to handle the Menu/Tool Bar and one to handle your Menu/Action items as outlined in Isma's answer – Dennis Jensen Aug 27 '19 at 15:17

1 Answers1

1

You could use a base class with a method to return either a list of QMenu items containing QAction items or a list of QAction items and then render them in your QMainWindow toolbar in whichever way you want, here is an example:

import sys
from PyQt5.QtWidgets import QAction, QApplication, QMainWindow, QMenu


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

    def menu_items(self)->list:
        pass


class Window1(WindowWithToolbar, QMainWindow):
    def __init__(self):
        WindowWithToolbar.__init__(self)
        QMainWindow.__init__(self)

        # New menu with actions
        self.menu = QMenu('one')
        self.menu.addActions([QAction('two', self), QAction('three', self)])

    def menu_items(self):
        return [self.menu]


class Window2(WindowWithToolbar, QMainWindow):
    def __init__(self):
        WindowWithToolbar.__init__(self)
        QMainWindow.__init__(self)

    def menu_items(self):
        # Only actions
        return [QAction('three', self), QAction('four', self)]


class MainWindow(WindowWithToolbar, QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self, parent=None)

        self.window1 = Window1()
        self.window2 = Window2()

        self.menu = QMenu('File')
        self.helloAction = QAction('Hello')
        self.menu.addAction(self.helloAction)

        self._build_menu()

    def menu_items(self)->list:
        return [self.menu]

    def _build_menu(self):
        self._add_menu_items(self)
        self._add_menu_items(self.window1)
        self._add_menu_items(self.window2)

    def _add_menu_items(self, windowWithToolbar: WindowWithToolbar):
        for menu_item in windowWithToolbar.menu_items():
            if isinstance(menu_item, QMenu):
                self.menuBar().addMenu(menu_item)
            elif isinstance(menu_item, QAction):
                self.menuBar().addAction(menu_item)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mw = MainWindow()
    mw.show()
    sys.exit(app.exec_())
Kermit
  • 4,922
  • 4
  • 42
  • 74
Isma
  • 14,604
  • 5
  • 37
  • 51