PyQt6主QMainWindow无法打开第二个QMainWindow子窗口问题咨询
问题根因
子窗口无法弹出、点击时程序崩溃的核心原因是子窗口实例被Python垃圾回收机制自动销毁。
在你当前实现的openchild_button_clicked方法中,child_window和child_ui都是函数内部的局部变量,点击事件对应的函数执行完成后,没有任何外部引用持有这两个对象,Python垃圾回收器会立刻回收这部分内存,对应的窗口自然无法正常显示,回收过程触发Qt底层内存访问异常时就会直接导致程序崩溃。
子窗口在__main__入口单独启动可以正常运行,是因为该场景下窗口实例定义在全局作用域,程序整个生命周期都持有有效引用,不会被回收。
修复方案
将子窗口实例绑定为父UI类的实例属性,保证对象持有长期有效引用即可,修改openchild_button_clicked方法如下:
def openchild_button_clicked(self): # 将子窗口、子UI绑定为当前类的实例属性,避免被GC回收 self.child_window = QtWidgets.QMainWindow() self.child_ui = Ui_ChildWindow() self.child_ui.setupUi(self.child_window) self.child_window.show()
如果需要避免重复点击弹出多个子窗口,可以在创建新实例前先判断是否存在已打开的子窗口,存在则先关闭销毁旧实例。
注意:不建议直接修改Qt Designer导出的Ui_*类代码,后续重新导出UI文件时会覆盖所有手动修改的内容,推荐通过继承Qt原生窗口类的方式封装业务逻辑。
父子窗口传值实现
你提到的在setupUi方法中传入参数是可行方案,更易维护的实现方式是自定义子窗口类,在初始化时接收父窗口传递的参数:
class ChildWindow(QtWidgets.QMainWindow): def __init__(self, selected_option, selected_object, parent=None): super().__init__(parent) self.ui = Ui_ChildWindow() self.ui.setupUi(self) # 存储父窗口传入的选中值,后续业务逻辑直接调用即可 self.selected_option = selected_option self.selected_object = selected_object
父窗口打开子窗口时直接传入对应选中值即可,同时传入父对象参数可以让Qt自动管理窗口层级:
def openchild_button_clicked(self): self.child_window = ChildWindow( selected_option = self.cb_cb2.currentText(), selected_object = self.cb_cb1.currentText(), parent = self ) self.child_window.show()
如果不想显式传参,也可以在子窗口逻辑中通过self.parent()获取父窗口实例,直接访问父窗口的控件属性读取选中值。
内容的提问来源于stack exchange,提问作者numbers1thru9
相关产品推荐
相关产品推荐

