PySide2跨窗口调用函数创建QStackedWidget报错解决
问题根因
报错本质是方法调用时的self绑定错误:
- 你写的
win1.creat_stackedwidget(self)属于类直接调用实例方法,传入的self是当前win2窗口的实例对象,不是win1的实例 creat_stackedwidget方法内部访问self.centralwidget时,实际是在win2对象上找该属性,而centralwidget是QMainWindow子类win1才有的UI元素,win2本身没有这个属性,直接抛出AttributeError
错误写法示例
你当前win2内的信号绑定逻辑大概率是这样:
# 错误:类直接调用实例方法,传入的self是win2实例 self.target_btn.clicked.connect(lambda: win1.creat_stackedwidget(self))
这也是为什么你在win1内部绑定按钮调用自身方法不报错——此时方法内的self就是win1实例本身,能正常访问centralwidget属性。
正确跨窗口调用实现
核心逻辑是:win2持有win1的实例引用,通过实例调用方法,不要直接用类名调用未绑定的实例方法。
第一步:修改win2类构造逻辑,接收主窗口实例
class win2(QtWidgets.QMainWindow, Ui_Form): def __init__(self, main_window, parent=None): super().__init__(parent) self.setupUi(self) # 保存传入的win1实例作为自身属性 self.main_window = main_window # 绑定按钮点击信号 self.create_stack_btn.clicked.connect(self._trigger_create_stack) def _trigger_create_stack(self): # 通过win1实例调用方法,此时方法内的self就是win1对象 self.main_window.creat_stackedwidget()
第二步:修改win1打开win2的逻辑,传入自身实例
class win1(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self.open_win2_btn.clicked.connect(self.open_win2) self._win2_ins = None # 持有win2实例引用,避免窗口被GC回收 self._stack_ins = None # 持有堆叠控件引用,避免重复创建 def open_win2(self): if not self._win2_ins: # 初始化win2时,把当前win1实例self传入 self._win2_ins = win2(main_window=self) self._win2_ins.show() def creat_stackedwidget(self): # 加重复判断,避免多次点击重复创建控件 if self._stack_ins: return self._stack_ins = QtWidgets.QStackedWidget() # 添加两个子页面 page_a = QtWidgets.QWidget() page_b = QtWidgets.QWidget() self._stack_ins.addWidget(page_a) self._stack_ins.addWidget(page_b) # 将堆叠控件加入主窗口中心部件的垂直布局 self.verticalLayout.addWidget(self._stack_ins)
避坑要点
- 所有Qt窗口类的实例方法,必须通过对应实例调用,不要直接用类名调用,除非你明确知道未绑定方法的传参规则
- 跨窗口交互时,通过构造函数传参传递目标对象引用即可,不要使用全局变量存窗口实例,避免出现作用域混乱、内存泄漏问题
- 动态创建UI控件时建议加重复判断,避免多次触发信号重复创建相同控件导致布局异常
内容的提问来源于stack exchange,提问作者Jhonatan Deni
相关产品推荐
相关产品推荐

