Change highlight color for a specific item (QAction type) on a QMenuBar

387 Views Asked by At

I want to mimic the behavior of the window top-right corner actions when hovering over the minimize-maximize-close buttons.

enter image description here enter image description here

So I have created a QMenuBar that contains 3 QActions.

class WindowMenuActions(QMenuBar):

    def __init__(self):
        super(WindowMenuActions, self).__init__()
        minimize_action = QAction(self)
        minimize_action.setIcon(_MINIMIZE_ICON)

        maximize_action = QAction(self)
        maximize_action.setIcon(_MAXIMIZE_ICON)

        exit_action = QAction(self)
        exit_action.setIcon(_CLOSE_ICON)
        
        self.addAction(minimize_action)
        self.addAction(maximize_action)
        self.addAction(exit_action)

And set the background color when hovering with stylesheet (it is applied to the entire QApplication):

I want the close button to have a different highlight color, so I tried setting a boolean property on the exit_action to change the color only for that specific item, but it does not do any effect (in fact, if I add the property in the stylesheet it doesn't even consider the stylesheet values)

Any idea of how to achieve this? To extend the question, I would not only use this for the minimize-maximize-close actions, but also to understand how to apply different hover/selected colors on QActions in the QMenuBar (not in the QMenu, which I already found a solution for that).

This is an running example:

from PySide2.QtWidgets import QMenuBar, QAction, QStyle, QApplication, QMainWindow
from PySide2.QtCore import Qt


class WindowMenuActions(QMenuBar):

    def __init__(self):
        super(WindowMenuActions, self).__init__()
        minimize_action = QAction(self)

        _MINIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMinButton)
        _MAXIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMaxButton)
        _EXIT_ICON = self.style().standardIcon(QStyle.SP_TitleBarCloseButton)

        minimize_action.setIcon(_MINIMIZE_ICON)
        minimize_action.setProperty('exit_action', False)

        maximize_action = QAction(self)
        maximize_action.setProperty('exit_action', False)
        maximize_action.setIcon(_MAXIMIZE_ICON)

        exit_action = QAction(self)
        exit_action.setProperty('exit_action', True)
        exit_action.setIcon(_EXIT_ICON)

        self.addAction(minimize_action)
        self.addAction(maximize_action)
        self.addAction(exit_action)
        self.setStyleSheet(
            'QMenuBar::item:selected {'
                'background-color: grey;'
            '}'
            'QMenuBar::item[exit_action=true]:selected {'
                ' background-color: red;'
            '}')


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    main = QMainWindow()
    main.setMenuBar(WindowMenuActions())
    main.show()
    sys.exit(app.exec_())
1

There are 1 best solutions below

2
On

To anyone interested, I sorted by inheriting from a regular QWidget instead of a QMenuBar and using QToolButton instead of QAction.

Working example:

from PySide2.QtWidgets import QMenuBar, QStyle, QApplication, QMainWindow, QWidget, QHBoxLayout, QToolButton, QMenu
from PySide2.QtCore import Qt

class MenuBar(QMenuBar):

    def __init__(self):
        super(MenuBar, self).__init__()

        self.addMenu(QMenu('File'))
        self.addMenu(QMenu('Help'))
        self.setCornerWidget(WindowMenuActions(self))


class WindowMenuActions(QWidget):

    def __init__(self, parent=None):
        super(WindowMenuActions, self).__init__(parent)

        _MINIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMinButton)
        _MAXIMIZE_ICON = self.style().standardIcon(QStyle.SP_TitleBarMaxButton)
        _EXIT_ICON = self.style().standardIcon(QStyle.SP_TitleBarCloseButton)

        minimize = QToolButton(self)
        minimize.setIcon(_MINIMIZE_ICON)

        maximize = QToolButton(self)
        maximize.setIcon(_MAXIMIZE_ICON)

        exit_action = QToolButton(self)
        exit_action.setProperty('exit_button', True)
        exit_action.setIcon(_EXIT_ICON)

        layout = QHBoxLayout()
        layout.addWidget(minimize)
        layout.addWidget(maximize)
        layout.addWidget(exit_action)
        self.setLayout(layout)

        self.setStyleSheet(
            'QToolButton:hover {'
                ' background: grey;'
            '}'
            'QToolButton[exit_button=true]:hover {'
            ' background: red;'
            '}'
        )


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    main = QMainWindow()
    main.setWindowFlags(Qt.FramelessWindowHint)

    main.setMenuBar(MenuBar())
    main.show()
    sys.exit(app.exec_())

enter image description here enter image description here