PyQt5中已打开窗口与未打开窗口间的变量传递问题
PyQt5主窗口向未打开子窗口传递变量的问题解决
你遇到的AttributeError核心原因有两个:
- 子窗口的
Ui_CalledWindow类从未定义过stringOut属性,主窗口的self.stringOut属于主窗口对象,子窗口无法直接访问; - 调用
setupUi初始化子窗口时,变量还未传递给子窗口,就直接执行self.listView.addItem(self.stringOut),导致属性不存在报错。
以下是两种可行的解决思路及代码修改:
方案1:修改子窗口setupUi方法,接收传递参数
直接在子窗口的初始化方法中添加参数,接收主窗口传递的字符串并初始化列表项:
修改后的calledWidget.py
from PyQt5 import QtCore, QtGui, QtWidgets class Ui_CalledWindow(object): # 新增string参数,默认值为None避免单独运行子窗口时报错 def setupUi(self, Dialog, string=None): Dialog.setObjectName("Dialog") Dialog.resize(612, 178) Dialog.setWindowTitle("Dialog") self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.listView = QtWidgets.QListWidget(Dialog) self.listView.setObjectName("listView") self.verticalLayout.addWidget(self.listView) # 仅当有传递字符串时才添加列表项 if string: self.listView.addItem(string) self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) Dialog = QtWidgets.QDialog() ui = Ui_CalledWindow() # 单独运行时可传入测试字符串 ui.setupUi(Dialog, "测试字符串") Dialog.show() sys.exit(app.exec_())
修改后的mainWidget.py(passString方法部分)
def passString(self): stringToPass = self.lineEdit.text() print(stringToPass) openingDialog = QMessageBox() openingDialog.setWindowTitle("Warning") openingDialog.setText("Are sure you want to pass the string: {}?".format(stringToPass)) openingDialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No) reply = openingDialog.exec() if reply == QMessageBox.Yes: self.newWindow = QtWidgets.QDialog() self.ui = Ui_CalledWindow() # 调用setupUi时传递字符串参数 self.ui.setupUi(self.newWindow, stringToPass) self.newWindow.show()
方案2:创建子窗口后直接操作其控件
无需修改子窗口的setupUi方法,在主窗口中完成子窗口初始化后,直接通过子窗口UI对象访问控件并添加内容:
修改后的mainWidget.py(passString方法部分)
def passString(self): stringToPass = self.lineEdit.text() print(stringToPass) openingDialog = QMessageBox() openingDialog.setWindowTitle("Warning") openingDialog.setText("Are sure you want to pass the string: {}?".format(stringToPass)) openingDialog.setStandardButtons(QMessageBox.Yes | QMessageBox.No) reply = openingDialog.exec() if reply == QMessageBox.Yes: self.newWindow = QtWidgets.QDialog() self.ui = Ui_CalledWindow() self.ui.setupUi(self.newWindow) # 直接操作子窗口的listView添加项 self.ui.listView.addItem(stringToPass) self.newWindow.show()
修改后的calledWidget.py
删除原代码中报错的self.listView.addItem(self.stringOut)行:
from PyQt5 import QtCore, QtGui, QtWidgets class Ui_CalledWindow(object): def setupUi(self, Dialog): Dialog.setObjectName("Dialog") Dialog.resize(612, 178) Dialog.setWindowTitle("Dialog") self.verticalLayout = QtWidgets.QVBoxLayout(Dialog) self.verticalLayout.setObjectName("verticalLayout") self.listView = QtWidgets.QListWidget(Dialog) self.listView.setObjectName("listView") self.verticalLayout.addWidget(self.listView) self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) Dialog = QtWidgets.QDialog() ui = Ui_CalledWindow() ui.setupUi(Dialog) Dialog.show() sys.exit(app.exec_())
两种方案各有适用场景:方案1适合需要在子窗口初始化阶段就使用参数的场景,方案2更灵活,适合初始化后动态传递数据的需求。
内容的提问来源于stack exchange,提问作者ARChalifour
相关产品推荐
相关产品推荐

