0

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)

musicamante
  • 41,230
  • 6
  • 33
  • 58
JareBear
  • 467
  • 9
  • 27
  • Sorry, but the code you provided really isn't a [reproducible example](https://stackoverflow.com/help/minimal-reproducible-example); please, edit it and ensure that it actually is **reproducible** without any external dependency or missing code excerpts, otherwise we'll not be able to help you. Also, I'd suggest you to avoid using upper case for variable names, as it's completely against the official [python style guide](https://www.python.org/dev/peps/pep-0008/) suggestions, making it hard to read and, consequentially, difficult to help you with. – musicamante Dec 15 '19 at 04:41
  • No need to be sorry, I am sorry for no following the guide lines, I fixed it now! – JareBear Dec 15 '19 at 04:51
  • Sorry to be sorry ;-) Your code is still not *reproducible*. There are a lot of things that appear on your example which are not declared anywhere (for instance, `dark_mode`, `self.checkboxClicked`, `self.verifyEmailAddress` and many others). Take your time, create a new folder with your example code and ensure that it successfully runs withour any unnecessary dependency, then use *that* code and edit your question afterwards. – musicamante Dec 15 '19 at 05:07
  • I am confused, those functions and variables are not there. I don't see them at all, I removed them.... I have tested the code, and its 100% reproducible – JareBear Dec 15 '19 at 05:18
  • for some reason the code shown before didn't update correctly. Now, the question is: is the problem about the QMenuBar not showing at its full size? – musicamante Dec 15 '19 at 05:34
  • Yes it is... im not sure what im doing wrong tho.. – JareBear Dec 15 '19 at 05:39
  • @JareBear I still don't understand why you don't use QMainWindow, what magic advantage does QWidget have that doesn't have QMainWindow? I ask because QMainWindow is a QWidget (that is, it inherits from QWidget), so all the QWidget features are QMainWindow – eyllanesc Dec 15 '19 at 05:49
  • The reason I use `QWidget` is because for some reason when I use `QMainWindow` I can't use `QGridLayout()` it doesn't load the layout.. and for `QWidget` it does.. – JareBear Dec 15 '19 at 05:56
  • @JareBear You can't set a layout on a QMainWindow, as it has its own layout that is used for widgets that are specific for it (the menubar, the statusbar, the dock widgets and the toolbars). You have to use a [centralWidget](https://doc.qt.io/qt-5/qmainwindow.html#creating-main-window-components), apply a layout to it and create your own GUI using that central widget as a parent. – musicamante Dec 15 '19 at 05:59

2 Answers2

2

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.

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • @JareBear I've updated my answer, please consider using the QMainWindow (and its behavior) if your only requirement was applying a specific layout. – musicamante Dec 15 '19 at 06:08
1

Set minimum width

self.setMinimumSize(320,240)