如何使用标志修改创建 QMessageBox 的子类?

Posted

技术标签:

【中文标题】如何使用标志修改创建 QMessageBox 的子类?【英文标题】:How do I make a subclass of QMessageBox with flag modifications? 【发布时间】:2020-04-21 15:41:08 【问题描述】:

我试图让 QMessageBox 中的文本可选择,我发现如果我修改 QMessageBox 上的“setTextInteractionFlags”,这可以解决问题。但是,当我尝试这样做时,我的 PyQt(或更具体地说,PySide)抱怨该属性不存在。所以我尝试将此功能添加为样式表,但是在尝试创建自己的 QMessageBox 自定义类时,这似乎根本不起作用。

然后我尝试手动制作一个 QMessageBox,这似乎可行。

代码如下:

from PyQt4 import QtCore
from PyQt4 import QtGui
import sys

class CustomQMessageBox(QtGui.QMessageBox):
    def __init__(self, *args, **kwargs):
        QtGui.QMessageBox.__init__(self, *args, **kwargs)
        self.setStyleSheet("QMessageBox  messagebox-text-interaction-flags: 5; ")


class Window(QtGui.QWidget):

    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.setWindowTitle('Test UI')
        self.setMinimumSize(225, 150)
        self.uiWidget = QtGui.QWidget()

        self.verticalLayout = QtGui.QVBoxLayout(self.uiWidget)

        self.enterListLabel = QtGui.QLabel(self.uiWidget)
        self.enterListLabel.setText('Enter list of names')
        self.verticalLayout.addWidget(self.enterListLabel)

        self.lyt = QtGui.QVBoxLayout()
        self.lyt.addWidget(self.uiWidget)

        self.setLayout(self.lyt)

        #This does NOT work
        cacheFixConfirm = CustomQMessageBox.question(self.uiWidget, 'Message Box', 'something', QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No)

        #This does
        confirmDialogBox = QtGui.QMessageBox()
        confirmDialogBox.setWindowTitle('Message Box')
        confirmDialogBox.setIcon(QtGui.QMessageBox.Question)
        confirmDialogBox.setText('sdlkfjl;asdjfosdijflsdkfjsdklfjsdkljfio')
        confirmDialogBox.setStyleSheet("QMessageBox  messagebox-text-interaction-flags: 5; ")
        confirmDialogBox.addButton(QtGui.QPushButton('Yes', parent=confirmDialogBox), QtGui.QMessageBox.YesRole)
        confirmDialogBox.addButton(QtGui.QPushButton('No', parent=confirmDialogBox), QtGui.QMessageBox.NoRole)
        confirmDialogBox.exec_()

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec_())

我只是想知道为什么第二个示例有效,而尝试使用自定义类的第一个示例却没有...

【问题讨论】:

【参考方案1】:

问题是静态方法aboutaboutQtcriticalinformationquestionwarning不使用派生类,而是使用QMessageBox,类似于:

class MessageBox(QMessageBox):
    @staticmethod
    def foo(self, arg1, ...):
        w = QMessageBox()
        ...

因此,即使您在 MessageBox 中设置了该属性,它也不会起作用,因为它不适用于不是 MessageBox 的类。

因此,根据您的需要,有以下选项:

    将相同的属性应用于所有现有的 QMessageBox(包括其派生类):
app.setStyleSheet("QMessageBox  messagebox-text-interaction-flags: 5; ")
    将样式表应用于在调用question() 方法时建立为父级的ui.Widget 将应用于您的所有子级:
self.uiWidget.setStyleSheet("QMessageBox  messagebox-text-interaction-flags: 5; ")
cacheFixConfirm = CustomQMessageBox.question(
    self.uiWidget,
    "Message Box",
    "something",
    QtGui.QMessageBox.StandardButton.Yes | QtGui.QMessageBox.StandardButton.No,
)
    不要使用静态方法。
messagebox = CustomQMessageBox(
    QtGui.QMessageBox.Question,
    "Message Box",
    "something",
    QtGui.QMessageBox.NoButton,
    self.uiWidget,
)
messagebox.addButton(QtGui.QMessageBox.Yes)
messagebox.addButton(QtGui.QMessageBox.No)
messagebox.exec_()

【讨论】:

嗯我想我明白你在说什么,仍然需要研究整个静态方法概念(和类方法)。但是我确实理解的是,您说除非我想影响所有 QMessageBox 实例,否则实际上无法通过子类化来做到这一点。所以我想类似于我的第二种方法,你的最后一个例子是要走的路。谢谢!

以上是关于如何使用标志修改创建 QMessageBox 的子类?的主要内容,如果未能解决你的问题,请参考以下文章

如何删除qmessage中自带的按钮

如何有一个特定的子命令需要带有 argparse 的标志?

55.Qt-将界面程序封装成静态库

55.Qt-将界面程序封装成静态库

如何禁用 Qt QMessageBox 播放的声音?

使用 QMessageBox 时无法使用 QThread 设置父错误