I made a QMenuBar with a QMenu with two actions. However I can't figure out how to style the dropdown that appears.
My attempt to style the dropdown just isn't working. From what I can tell, QAction can't be given styles, so I tried QMenu but that doesn't work either. So I'm not sure how to style this dropdown...
OS: Windows 11 Using PyQt5
from PyQt5.QtWidgets import QApplication, QWidget, QMenuBar, QMenu, QAction, QVBoxLayout, QMainWindow
class test(QMainWindow):
def __init__(self):
super(test, self).__init__()
self.setWindowTitle('test')
self.resize(200,200)
self.mainWindow = QWidget()
self.mainLayout = QVBoxLayout()
self.bar = QMenuBar()
self.menuItem = QMenu('Help')
self.bar.addMenu(self.menuItem)
self.menuAction = QAction('Action')
self.menuItem.addAction(self.menuAction)
self.mainLayout.addWidget(self.bar)
self.mainWindow.setStyleSheet("""
QWidget {
background-color: #222;
color: #cfcfcf;
font-family: Roboto;
font-size: 14pt;
}
QMenuBar {
background-color: #222;
padding-top: 4px;
}
QMenuBar::item {
border-radius: 4px;
border-width: 0;
padding: 4px 8px;
}
QMenuBar::item:selected {
background-color: #777777;
}
QMenu, QAction {
background-color: red;
border-radius: 4px;
border-width: 0;
}
QMenu::item {
color: blue;
}
QMenu::item:selected {
background-color: aqua;
color: orange;
}
""")
self.mainWindow.setLayout(self.mainLayout)
self.setCentralWidget(self.mainWindow)
if __name__ in '__main__':
app = QApplication([])
main = test()
main.show()
app.exec_()
Your code has many conceptual issues, with most of them causing the result you're facing.
First of all, QMainWindow already provides a "menu bar" API (see menuBar()
). You should not try to add a QMenuBar on the central widget, unless you really know what you're doing.
Then, Qt Style Sheets are applied to related widgets only when they are children of the widget they're set on. Creating a separate QMenu that is added to a QMenu or QMenuBar does not create a parent/child relation.
You are setting the stylesheet on the mainWindow
widget, but the menuItem
is a standalone QMenu that has absolutely no parent, therefore it will not inherit the stylesheet. Adding a "foreign" menu to another QMenu or QMenuBar will NOT make that menu a child of them.
Considering the above, the simplest (yet not completely appropriate) solution would be to change the setStyleSheet()
call to this:
QApplication.instance().setStyleSheet("""
...
""")
Note, though, that this wouldn't be completely appropriate, mostly because it would apply the style sheet to any widget within the application, which may not be desirable.
Also, a widget should not be able to set such a global aspect that may affect other and unrelated widgets as well.
Even ignoring the menuBar()
API mentioned above, it's normally preferable to use QLayout.setMenuBar()
instead of addWidget()
.
Also, unless you need a global/more flexible usage of an action, you should use the addAction()
overloads of QMenu (such as this), instead of adding a manually created QAction.
The following changes would properly fix the issue:
class test(QMainWindow):
def __init__(self):
...
self.bar = self.menuBar()
self.menuItem = self.bar.addMenu('Help')
self.menuAction = self.menuItem.addAction('Action')
self.setStyleSheet("""
...
""")
Note that I left the self.bar
attribute creation, even though it's not necessary (nor very appropriate): you could just create a local variable (eg: bar = self.menuBar()
) as a convenience reference within the context of the function, but it would be more appropriate to always use self.menuBar()
anywhere else in the context of the QMainWindow subclass, unless you're completely sure that the menu bar isn't changed at runtime with another one.
Other unrelated but still important issues:
mainWindow
is clearly inappropriate other than confusing;QWidget {}
selector) is always discouraged as it may affect the appearance of complex widgets such as QComboBox, QSlider and scroll areas (see the note at the end of the Sub-Ccontrols documentation); don't do it unless you really know what you're doing;super()
within the same class context;exec
, as it's not a protected keyword anymore in Python 3; get rid of that character as that attribute may not be available in future PyQt versions;