You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5中已打开窗口与未打开窗口间的变量传递问题

PyQt5主窗口向未打开子窗口传递变量的问题解决

你遇到的AttributeError核心原因有两个:

  1. 子窗口的Ui_CalledWindow类从未定义过stringOut属性,主窗口的self.stringOut属于主窗口对象,子窗口无法直接访问;
  2. 调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 21:01:07