有没有办法改变所有 QMessageBox 的 OK 按钮的样式表?

Is there a way to change the stylesheet of just OK button of all the QMessageBox?

我想让我的 GUI 中所有 QMessageBox 的确定按钮(这很复杂,所以有很多)相对于其他按钮设置不同的颜色(取消, 没有等等).

我不想每次创建新的时候都设置它的颜色QMessageBox,但我想通过我的应用程序的样式表一劳永逸地设置它。

我尝试了不同的选项,但 none 个选项有效:

 - QMessageBox#okButton {background-color:blue}
 - QMessageBox::okButton {...}
 - QMessageBox:okButton {...}
 - QMessageBox#ok-button {...}
 - QMessageBox QPushButton#okButton {...}

和其他人...

有什么办法还是必须放弃?

一个可能的解决方案是将 objectName() 设置为每个按钮的选择器,为此您可以使用 QApplication:

notify() 方法
from PySide2.QtCore import QEvent
from PySide2.QtWidgets import *


class Application(QApplication):
    def notify(self, receiver, event):
        if isinstance(receiver, QMessageBox) and event.type() == QEvent.Show:
            for button in receiver.buttons():
                sb = receiver.standardButton(button)
                if not button.objectName():
                    button.setObjectName(sb.name.decode())
                    button.style().unpolish(button)
                    button.style().polish(button)
        return super().notify(receiver, event)


def main():
    app = Application()
    app.setStyle("fusion")

    app.setStyleSheet(
        """
    QPushButton#Ok { background-color: green }
    QPushButton#Cancel { background-color: red }
    """
    )

    QMessageBox.critical(
        None, "Title", "text", buttons=QMessageBox.Ok | QMessageBox.Cancel
    )

    msgBox = QMessageBox()
    msgBox.setText("The document has been modified.")
    msgBox.setInformativeText("Do you want to save your changes?")
    msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
    msgBox.exec_()


if __name__ == "__main__":
    main()

不幸的是,没有直接的解决方案,因为 QDialogBu​​ttonBox(这是 QMessageBox 用于其按钮的)不提供按钮角色的选择器。

对于静态创建的消息框,唯一的方法是使用 [text="button text"] 选择器,但这只是一个猜测,可能会根据本地化和样式(可以设置助记符,和您甚至无法确定那是什么)。此外,这需要为 QApplication 设置样式表。

适用于这些情况的可能的应用程序范围样式表如下所示:

app.setStyleSheet('''
    QDialogButtonBox > QPushButton[text="&OK"] {
        background-color: orange;
    }
    QDialogButtonBox > QPushButton[text="&Cancel"] {
        background-color: green;
    }
''')

请注意,我使用了 Parent > Class 选择器以确保只有 QDialogBu​​ttonBox 的按钮具有这些规则的样式,否则 any “确定”按钮将是橙色的等

尽管如此,在我的计算机上的上述情况下,它仅适用于“确定”按钮,因为我的本地化(意大利语)对另一个使用“&Annulla”。

另一方面,如果您要创建 QMessageBox 实例,则使用基于对象名称的选择器会更加自由和灵活。

唯一的问题是,由于对象名称是在创建后设置的,因此未应用样式表,因此按钮在实例化后必须“未抛光”。

一个简单的子类可以提供一个标准的接口,而不会使事情过于复杂:

class ColoredMessageBox(QtWidgets.QMessageBox):
    StandardNames = {
        QtWidgets.QMessageBox.Ok: 'Ok', 
        QtWidgets.QMessageBox.Cancel: 'Cancel', 
        QtWidgets.QMessageBox.Save: 'Save', 
        # ...
    }
    def exec_(self):
        for button in self.buttons():
            objName = self.StandardNames.get(self.standardButton(button))
            if objName:
                button.setObjectName(objName)
            self.style().unpolish(button)
        return super().exec_()

import sys
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet('''
    QMessageBox > QDialogButtonBox > QPushButton#Ok {
        background-color: orange;
    }
    QMessageBox > QDialogButtonBox > QPushButton#Cancel {
        background-color: blue;
    }
''')
w = ColoredMessageBox(QtWidgets.QMessageBox.Information, 'Hello', 'How are you?', 
    QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel)
w.exec_()