簡體   English   中英

從向導/對話框中接受/完成的信號中檢索值的Qt規范方法

[英]Qt canonical way of retrieving values from Wizard / Dialog on accepted / finished signal

我正在使用PyQt,但我想同樣的問題也適用於Qt C ++。

假設我有一個帶按鈕的主窗口,該按鈕會打開一個向導來收集數據,並且在向導關閉后需要在主窗口中使用數據。 標准程序。

因此,有多種方法可以做到這一點。 要么我可以將對主窗口的引用傳遞給向導,然后它使用主窗口引用完成所有工作,但是我要說這破壞了模塊化。 我還可以將回調連接到向導accepted rejectedfinished信號,但是在該回調中,我沒有對向導本身的引用,因此無法獲取向導字段中的數據。 除非我將對向導的引用存儲為實例變量,以便從回調中再次訪問它。

另一個選擇是(即使我尚未完全理解)使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM