[英]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.