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

Qt主窗口动态切换中央部件报错:wrapped c/c++ object已删除

解决QMainWindow切换中央部件时控件被销毁的问题

嘿,我完全懂你遇到的困扰——前几次点击按钮还正常,之后就弹出控件已被删除的报错,这其实是Qt的对象父子销毁机制在起作用,咱们一步步拆解问题和解决方案:

问题根源

当你调用self.setCentralWidget(wid)时,Qt会自动销毁上一次设置的中央部件(也就是之前创建的那个wid对象)。而你把self.lineedit、self.checkbox这些控件添加到了wid的布局里后,这些控件会自动成为wid的子对象。根据Qt的规则:父对象被销毁时,所有子对象会被一并销毁。

所以第一次切换后,旧的wid被删除,里面的那个随机选中的控件也跟着没了。之后再尝试把这个已经被销毁的控件加到新布局里,自然就会触发“wrapped c/c++ object has been deleted”的报错。

两种解决方案

方案1:每次创建新的控件实例(简单直接)

如果不需要保留控件的状态(比如输入的文本、勾选状态),可以每次随机生成新的控件对象,这样就不会遇到旧对象被销毁的问题:

import sys
import random
from PyQt5 import QtWidgets

class window25(QtWidgets.QMainWindow):
    def __init__(self):
        try:
            super(window25,self).__init__()
            self.btn=QtWidgets.QPushButton("press me")
            self.guichange()
            self.btn.clicked.connect(self.guichange)
            self.show()
        except Exception as E:
            print(E)
    def guichange(self):
        try:
            wid=QtWidgets.QWidget()
            myLayout=QtWidgets.QVBoxLayout()
            myLayout.addWidget(self.btn)
            # 每次随机创建新的控件实例
            chosen_widget = random.choice([
                QtWidgets.QLineEdit(),
                QtWidgets.QCheckBox(),
                QtWidgets.QRadioButton()
            ])
            myLayout.addWidget(chosen_widget)
            wid.setLayout(myLayout)
            self.setCentralWidget(wid)
        except Exception as E:
            print(E)

app=QtWidgets.QApplication([])
ex=window25()
sys.exit(app.exec_())

方案2:复用原有控件并避免被销毁(保留状态)

如果需要保留控件的状态(比如输入的文本、勾选状态),可以在每次切换前把控件从旧布局中移除,并解除它们和旧父对象的关联:

import sys
import random
from PyQt5 import QtWidgets

class window25(QtWidgets.QMainWindow):
    def __init__(self):
        try:
            super(window25,self).__init__()
            # 保存所有需要复用的控件到列表
            self.reusable_widgets = [
                QtWidgets.QLineEdit(),
                QtWidgets.QCheckBox(),
                QtWidgets.QRadioButton()
            ]
            self.btn=QtWidgets.QPushButton("press me")
            self.guichange()
            self.btn.clicked.connect(self.guichange)
            self.show()
        except Exception as E:
            print(E)
    def guichange(self):
        try:
            wid=QtWidgets.QWidget()
            myLayout=QtWidgets.QVBoxLayout()
            myLayout.addWidget(self.btn)
            
            # 先解除所有复用控件和旧父对象的关联
            for widget in self.reusable_widgets:
                if widget.parent() is not None:
                    widget.setParent(None)
            
            # 随机选择一个控件添加到新布局
            chosen_widget = random.choice(self.reusable_widgets)
            myLayout.addWidget(chosen_widget)
            
            wid.setLayout(myLayout)
            self.setCentralWidget(wid)
        except Exception as E:
            print(E)

app=QtWidgets.QApplication([])
ex=window25()
sys.exit(app.exec_())

改动说明

  • 方案1去掉了初始化时创建的控件实例,每次切换都生成新对象,彻底避免了旧对象被销毁的问题。
  • 方案2通过widget.setParent(None)解除控件和旧父对象的绑定,这样旧的中央部件被销毁时,这些控件不会被连带删除,就能安全复用了。

内容的提问来源于stack exchange,提问作者Nimish Bansal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:25:50