[英]Qt canonical way of retrieving values from Wizard / Dialog on accepted / finished signal
我正在使用PyQt,但我想同样的问题也适用于Qt C ++。
假设我有一个带按钮的主窗口,该按钮会打开一个向导来收集数据,并且在向导关闭后需要在主窗口中使用数据。 标准程序。
因此,有多种方法可以做到这一点。 要么我可以将对主窗口的引用传递给向导,然后它使用主窗口引用完成所有工作,但是我要说这破坏了模块化。 我还可以将回调连接到向导accepted
rejected
或finished
信号,但是在该回调中,我没有对向导本身的引用,因此无法获取向导字段中的数据。 除非我将对向导的引用存储为实例变量,以便从回调中再次访问它。
另一个选择是(即使我尚未完全理解)使用https://doc.qt.io/qt-5/qobject在回调中获取对信号发射器(即向导)的引用。 html#sender 。 但这似乎不建议。
那么规范的方式是什么?
前提:这是一个基于观点的问题,因为没有一种且只有一种 “好的”方式可以做到这一点。 我只是想发表评论(SO中不建议基于意见的答案/问题),但是有限的格式不是很有帮助。
“通过引用”并不一定会破坏模块化。
取而代之的是QDialog通常被初始化的内容:父级是“调用”窗口,这也是QDialog如何对父级或整个应用程序进行“模态化”(这意味着只要在对话框外不允许交互,它是活动的)。
AFAIK,我不知道这是否真的被认为是规范的 ,但是以下是最常用的建议方法。
这个想法是,您有一个子对象(通常是QDialog),它可能会或可能不会在每次需要时初始化,这取决于您; 重要的一点是,至少在更新其结果所需的时间内,您需要对其进行引用,这甚至可能在单个方法/槽的范围内发生。
from PyQt5 import QtWidgets
class MyWizard(QtWidgets.QDialog):
def __init__(self, parent=None):
super().__init__(parent)
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
self.checkBox = QtWidgets.QCheckBox('check')
layout.addWidget(self.checkBox)
self.input = QtWidgets.QLineEdit()
layout.addWidget(self.input)
buttonBox = QtWidgets.QDialogButtonBox(QtWidgets.QDialogButtonBox.Ok|QtWidgets.QDialogButtonBox.Cancel)
layout.addWidget(buttonBox)
buttonBox.accepted.connect(self.accept)
buttonBox.rejected.connect(self.reject)
def setData(self, **data):
self.checkBox.setChecked(data.get('check', False))
self.input.setText(data.get('text', ''))
def getData(self):
return {'check': self.checkBox.isChecked(), 'text': self.input.text()}
def exec_(self, **data):
self.setData(**data)
return super().exec_()
class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
centralWidget = QtWidgets.QWidget()
self.setCentralWidget(centralWidget)
layout = QtWidgets.QHBoxLayout()
centralWidget.setLayout(layout)
self.showWizBtn = QtWidgets.QPushButton('Show wizard')
layout.addWidget(self.showWizBtn)
self.showWizBtn.clicked.connect(self.getDataFromWizard)
self.data = {}
def getDataFromWizard(self):
wiz = MyWizard(self)
if wiz.exec_(**self.data):
self.data.update(wiz.getData())
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
另一种可能性是创建一个持久的子对话框(但请记住,如果父级可以更改数据,则至少在执行时,必须找到一种更新方法); 这里的概念是,您可以在需要时执行对话框,并且将accepted
信号连接到可以从对话框获取数据的插槽。 这不是常见用途(也不建议使用IMHO),并且仅应用于非常特殊的情况。
正如您已经发现的,不建议使用sender
:信号是异步的,并且在正常情况下发送器是可靠的,除非绝对必要,否则最好避免使用它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.