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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:33:22