我创建了一个小pyqt5项目。这是运行时应用程序的打印屏幕:
当用户点击主窗口中的QPushButton
时,会出现对话窗口,用户会在QlineEdit
中写入内容。然后在单击对话框窗口的QPushButton
时,对话框窗口会向主窗口发送信号并被删除。信号包含用户输入的文本。
以下是我的两个类的描述,非常简单:
MainWindow类。
DialogWindow类(我想在不使用预先存在的Dialog窗口的情况下创建自己的Dialog类。)
我的主要脚本
我有几个问题:
使用信号以便在窗口之间进行通信是否正确?我不认为我违反了类封装。但是,我不喜欢通过写:
来连接子类的信号self.mySignal.connect(parent.updatelabelAnswer)
在这一行中,我使用属性parent
- 它没关系吗?在我看来,这不是一种使用信号的好方法。
我的第二个问题是:
我是否可以在self.deleteLater()
的{{1}}位置拨打on_pushButton_clicked
?似乎没有,因为我已经检查了python交互式shell并且仍然可以访问对象DialogWindow
。
答案 0 :(得分:1)
好吧所以我想我应该发一个答案,而不是写臃肿的评论:P
关于删除,我将引用Qt documentation:
与QWidget :: close()一样,如果是,则done()删除对话框 设置Qt :: WA_DeleteOnClose标志。如果对话框是应用程序的 主要小部件,应用程序终止。如果对话框是最后一个 窗口关闭,发出QApplication :: lastWindowClosed()信号。
但是,如果要从打开它的其他窗口小部件处理对话窗口的关闭(和删除),则应使用插槽和信号。只需将主要小部件中的按钮或其他内容及其clicked()
信号连接到对话框的done()
插槽,即可开始使用。
此时我还想指出删除对话框可能没有必要。根据对话框的内存占用量(用于创建和运行内存的内存量),您可能希望考虑在开始时创建对话框并将其留在内存中,直到主应用程序关闭为止。除此之外,您还可以使用hide()
和show()
在屏幕上显示它。对于足够小的事情来说,这实际上是一种很好的做法,因为与简单地隐藏和显示窗口相比,删除然后创建窗口需要更多时间。
现在关于信号和插槽,它们具有非常简单的语义。正如我在评论和我的其他answer中发布的那样,为了将插槽连接到信号,您需要将它们放在同一范围内。如果不是这种情况,则将一个(或两个)传递到情况得到修复的地方。在你的情况下,你必须有一个共同的地方。如果两者都是顶级小部件,则必须在main()
内建立连接。我宁愿将对话框添加为MainWindow
类(作为类成员)和实例化以及那里的连接的扩展 - 例如在MainWindow
的构造函数中:
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.setupUi(self)
self.dialog = DialogWindow(self)
# Connect mainwindow's signals to dialog's slots
# Connect dialog's signals to mainwindow's slots
# And even connect dialog's signals to dialog's slots
答案 1 :(得分:1)
通常,父母应始终是执行信号连接的父母。让子窗口小部件在父窗口上建立连接是有问题的,因为它对父窗口施加限制并导致副作用,并且在子窗口小部件的父所有权被转移的情况下完全中断。
在您的示例中,我会考虑两个选项"更正"。如果对话框至少在某种程度上是持久的,并且不打算以模态方式运行,那么它应该定义父类连接到的信号。对话框不应该自行删除,这应该是收到信号后父类的责任。
<强>主窗口强>
def on_pushbutton_clicked(self):
if not self.dlg:
self.dlg = DialogWindow(self)
self.dlg.mySignal.connect(self.on_mySignal)
self.dlg.show()
def on_mySignal(value):
self.dlg.mySignal.disconnect()
self.dlg.close()
self.dlg.deleteLater()
self.dlg = None
self.updateLabelAnswer(value)
您的对话框似乎是一个临时对话框,仅用于收集输入,应该以模态方式运行。在这种情况下,您甚至不必定义任何信号。只需创建类并提供API即可获取文本框的值。
<强> DialogWindow 强>
class DialogWindow(...)
...
def on_pushbutton_clicked(self):
self.accept()
def getValue(self):
return self.lineEdit.text()
在MainWindow
def on_pushbutton_clicked(self):
dlg = DialogWindow(self)
if dlg.exec_():
value = dlg.getValue()