首页 > 解决方案 > Python PyQt5 将不再显示此消息复选框添加到 QMessageBox

问题描述

我正在努力让这个工作。我试图从一个 c++ 帖子转换成 python 没有快乐: QMessageBox 带有“不再显示这个”复选框

我的粗略代码如下:

from PyQt5 import QtWidgets as qtw

...
mb = qtw.QMessageBox
cb = qtw.QCheckBox

# following 3 lines to get over runtime errors
# trying to pass the types it was asking for
# and surely messing up
mb.setCheckBox(mb(), cb())
cb.setText(cb(), "Don't show this message again")
cb.show(cb())
ret = mb.question(self,
                 'Close application',
                 'Do you really want to quit?',
                 mb.Yes | mb.No )
if ret == mb.No:
   return
self.close()

以上执行没有错误,但复选框未显示(消息框显示)。考虑到我在基因上很愚蠢......而且很慢,非常慢。所以请在我的学习曲线上放轻松

标签: pythonpyqt5

解决方案


在尝试“移植”代码时,了解源语言的基础并对目标有更深入的了解非常重要。

例如,获取代码的第一行和引用的问题:

QCheckBox *cb = new QCheckBox("Okay I understand");

上面的 C++ 行表示正在创建一个 QCheckBox 类型的新对象 (cb),并为其分配了 的结果QCheckBox(...),它返回该类的一个实例。为了阐明对象是如何声明的,下面是一个简单的整数变量的创建方式:

int mynumber = 10

这是因为 C++ 和许多语言一样,需要对象类型来声明。

在 Python 中,这是一种动态类型语言,这不是必需的(但从Python 3.6 开始可以),但您仍然需要创建实例,这通过使用类上的括号来实现的(这导致调用它并导致调用和然后)。你的代码的前两行应该是:__new____init__

mb = qtw.QMessageBox()
cb = qtw.QCheckBox()

然后,问题是您每次都使用上述类的新实例调用其他方法。

以实例作为第一个参数隐式调用实例方法(例如setCheckBox),通常称为self

checkboxInstance = QCheckBox()
checkboxInstance.setText('My checkbox')
# is actually the result of:
QCheckBox.setText(checkboxInstance, 'My checkbox')

最后一行或多或少意味着:调用setText类 QCheckBox 的函数,使用实例和文本作为其参数。事实上,如果 QCheckBox 是一个实际的 python 类,setText()它看起来像这样:

class QCheckBox:
    def setText(self, text):
        self.text = text

当您这样做时,cb = qtw.QCheckBox您只创建了对该类的另一个引用,并且每次cb()您创建一个新实例;也是如此mb,因为您创建了对消息框类的另一个引用。

以下行:

mb.setCheckBox(mb(), cb())

是相同的:

QMessageBox.setCheckBox(QMessageBox(), QCheckBox())

由于您每次都在创建新实例,因此结果绝对没有:没有对新实例的引用,并且在处理该行后它们将立即被丢弃(“垃圾收集”,也就是删除)。

这就是上述实际应该如何完成的:

mb = qtw.QMessageBox()
cb = qtw.QCheckBox()

mb.setCheckBox(cb)
cb.setText("Don't show this message again")

现在,您的代码中有一个根本缺陷:question()是一个静态方法(实际上,对于 Python,它更像是一个类方法)。静态方法和类方法是不作用于实例的函数,而只作用于/作用于类。QMessageBox 的静态方法喜欢question或使用提供的参数warning创建 QMessageBox 的新实例,因此您之前在创建的实例上所做的一切都将被完全忽略。

这些方法是方便的函数,无需编写太多代码即可简单地创建消息框。由于这些方法只允许基于它们的参数进行定制(不包括添加复选框),因此您显然不能使用它们,并且您必须明确编码它们“在幕后”所做的事情。

以下是最终代码的外观:

    # create the dialog with a parent, which will make it *modal*
    mb = qtw.QMessageBox(self)
    mb.setWindowTitle('Close application') 
    mb.setText('Do you really want to quit?') 
    # you can set the text on a checkbox directly from its constructor
    cb = qtw.QCheckBox("Don't show this message again")
    mb.setCheckBox(cb)
    mb.setStandardButtons(mb.Yes | mb.No)
    ret = mb.exec_()
    # call some function that stores the checkbox state
    self.storeCloseWarning(cb.isChecked())
    if ret == mb.No:
        return
    self.close()

推荐阅读