接受/完成符号时从向导/对话框检索值的Qt规范方法

2024-10-01 04:54:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用PyQt,但我猜同样的问题也适用于Qt C++。你知道吗

假设我有一个带有按钮的主窗口,该按钮打开一个收集数据的向导,并且在向导关闭后,需要在主窗口中使用数据。标准程序。你知道吗

所以有多种方法可以做到这一点。或者我可以将对主窗口的引用传递给向导,它使用主窗口引用完成所有工作,但我认为这破坏了模块化。我还可以将回调连接到向导acceptedrejectedfinished信号,但在该回调中,我没有对向导本身的引用,因此无法访问向导字段中的数据。除非我将对向导的引用存储为实例变量,以便从回调中再次访问它。你知道吗

另一个选项是(尽管我还没有完全理解它)在回调中使用https://doc.qt.io/qt-5/qobject.html#sender获取对信号发射器(即向导)的引用。但这似乎并不可取。你知道吗

那么规范的方法是什么呢?你知道吗


Tags: 数据实例方法https程序标准信号选项
1条回答
网友
1楼 · 发布于 2024-10-01 04:54:58

前提:这是一个基于观点的问题,因为没有一个也只有一个“好”的方法。我只是想发表评论(这里不鼓励基于观点的回答/问题),但有限的格式并没有太大帮助。你知道吗

“传递引用”并不一定会破坏模块化。
相反,这正是QDialog通常被初始化的地方:父级是“调用”窗口,这也是QDialog对父级或整个应用程序的“模态”方式(意味着只要对话框处于活动状态,就不允许在对话框之外进行任何交互)。你知道吗

好吧,我不知道这是否真的被认为是规范的,但下面是最常见的建议方法 这个想法是你有一个子对象(通常是一个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:信号是异步的,虽然在正常情况下发送方是可靠的,但除非绝对必要,否则最好避免使用它。你知道吗

相关问题 更多 >