Python PyQt5 how to show the full QMenuBar with a QWidget

Question:

I’m getting this weird result when using QMenuBar I’ve used this exact code before for the QMenuBar and it worked perfectly. But it doesn’t show more than 1 QMenu

This is my code:

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

import sys
from functools import partial

class MainMenu(QWidget):
    def __init__(self, parent = None):
        super(MainMenu, self).__init__(parent)
        # background = QWidget(self)
        lay = QVBoxLayout(self)
        lay.setContentsMargins(5, 35, 5, 5)
        self.menu()
        self.setWindowTitle('Control Panel')
        self.setWindowIcon(self.style().standardIcon(getattr(QStyle, 'SP_DialogNoButton')))
        self.grid = QGridLayout()
        lay.addLayout(self.grid)
        self.setLayout(lay)
        self.setMinimumSize(400, 320)


    def menu(self):
        menubar = QMenuBar(self)

        viewMenu = menubar.addMenu('View')
        viewStatAct = QAction('Dark mode', self, checkable=True)
        viewStatAct.setStatusTip('enable/disable Dark mode')
        viewMenu.addAction(viewStatAct)

        settingsMenu = menubar.addMenu('Configuration')
        email = QAction('Set Email', self)
        settingsMenu.addAction(email)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = MainMenu()
    main.show()
    sys.exit(app.exec_())

Result:

enter image description here

I am aware that I am using QWidget when I should be using QMainWindow But is there a workaround???

(I apologize in advance for the terrible quality of the image, there is no good way to take a picture of a QMenuBar)

Asked By: JareBear

||

Answers:

The problem is that with a QWidget you are not using the "private" layout that a QMainWindow has, which automatically resizes specific children widgets (including the menubar, the statusbar, the dock widgets, the toolbars and, obviously, the "centralWidget").
Remember that a QMainWindow has its own layout (which can’t and shouldn’t be changed), because it needs that specific custom layout to lay out the aforementioned widgets. If you want to set a layout for the main window, you’ll need to apply it to its centralWidget.

Read carefully how the Main Window Framework behaves; as the documentation reports:

Note: Creating a main window without a central widget is not supported. You must have a central widget even if it is just a placeholder.

In order to work around that when using a basic QWidget, you’ll have to manually resize the children widgets accordingly. In your case, you only need to resize the menubar, as long as you have a reference to it:

    def menu(self):
        self.menubar = QMenuBar(self)
        # any other function has to be run against the *self.menubar* object
        viewMenu = self.menubar.addMenu('View')
        # etcetera...

    def resizeEvent(self, event):
        # calling the base class resizeEvent function is not usually
        # required, but it is for certain widgets (especially item views 
        # or scroll areas), so just call it anyway, just to be sure, as
        # it's a good habit to do that for most widget classes
        super(MainMenu, self).resizeEvent(event)
        # now that we have a direct reference to the menubar widget, we are
        # also able to resize it, allowing all actions to be shown (as long
        # as they are within the provided size
        self.menubar.resize(self.width(), self.menubar.height())

Note: you can also "find" the menubar by means of self.findChild(QtWidgets.QMenuBar) or using the objectName, but using an instance attribute is usually an easier and better solution.

Answered By: musicamante

Set minimum width

self.setMinimumSize(320,240)
Answered By: AMAR
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.