已删除QWidget类型的包装c/c++对象

2024-09-28 18:51:33 发布

您现在位置:Python中文网/ 问答频道 /正文

class window25(QtWidgets.QMainWindow):
    def __init__(self):
        try:
            super(window25,self).__init__()
            self.lineedit=QtWidgets.QLineEdit()
            self.checkbox=QtWidgets.QCheckBox()
            self.optBox=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()
    #        self.setCentralWidget()
            myLayout=QtWidgets.QVBoxLayout()
            myLayout.addWidget(self.btn)
            myLayout.addWidget(random.choice([self.lineedit,self.checkbox,self.optBox]))
            wid.setLayout(myLayout)    
            self.setCentralWidget(wid)
        except Exception as E:
            print(E)


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

我想做的是实验。不过我知道QStackedWidget可以更改窗口,但我尝试了其他方法,即按一个按钮随机更改主窗口中心小工具。之后有几次成功(即按下按钮3、4次都能正常工作),但之后我遇到了一个错误

wrapped c/c++ object of type QCheckBox has been deleted

wrapped c/c++ object of type QLineEdit has been deleted

我无法理解是哪个语句导致了这个错误,以及为什么我错了或者哪里错了


Tags: selfinitdeftrycheckboxbtnmylayoutqtwidgets
1条回答
网友
1楼 · 发布于 2024-09-28 18:51:33

这是由Qt的实现和原理引起的,回顾观察到的documentation

[...]

QObjects organize themselves in object trees. When you create a QObject with another object as parent, the object will automatically add itself to the parent's children() list. The parent takes ownership of the object; i.e., it will automatically delete its children in its destructor. You can look for an object by name and optionally type using findChild() or findChildren().

[...]

正如他所说,如果父控件也破坏了子控件,并且由于所有小部件都有QObject作为它们的前身,它们也会遵守这些规则。在

但为什么有些小部件会被销毁?

每次使用setCentralWidget()时,以前作为中心小部件的对象将被删除。在

CentralWidget()的子级是什么?

当小部件附加到布局时,这些小部件被设置为使用该布局的小部件的父级。在

wid = QtWidgets.QWidget()   
myLayout.addWidget(tmp)    
wid.setLayout(myLayout)    
self.setCentralWidget(wid) 

为什么QPushButton没有被消除?

使用QPushButton和其他小部件的情况是,在使用setCentralWidget()(即删除父对象)之前,它会从父窗口更改:

^{pr2}$

最后,我将使用以下代码解释一个随机示例:

class window25(QtWidgets.QMainWindow):
    counter = 0
    def __init__(self):
        try:
            super(window25,self).__init__()
            self.lineedit=QtWidgets.QLineEdit()
            self.lineedit.setObjectName("QLineEdit")
            self.checkbox=QtWidgets.QCheckBox()
            self.checkbox.setObjectName("QCheckBox")
            self.optBox=QtWidgets.QRadioButton()
            self.optBox.setObjectName("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:
            print("\ncall guichange")
            wid = QtWidgets.QWidget()
            wid.setObjectName("wid-{}".format(self.counter))
            myLayout=QtWidgets.QVBoxLayout()
            myLayout.addWidget(self.btn)
            tmp = random.choice([self.lineedit,self.checkbox,self.optBox])
            myLayout.addWidget(tmp)
            wid.setLayout(myLayout)    
            wid.destroyed.connect(lambda obj: print("delete: ",obj.objectName()))
            tmp.destroyed.connect(lambda obj: print("delete: ",obj.objectName()))
            self.setCentralWidget(wid)
            print("add: {} parent: {}".format(tmp.objectName(),tmp.parent().objectName()))
            self.counter += 1

        except Exception as E:
            print(E)

说明:

call guichange
QLineEdit                      # tmp is QLineEdit
add: QLineEdit parent: wid-0   # set to wid-0 as the parent of QLineEdit

call guichange
QLineEdit                      # tmp is QLineEdit
add: QLineEdit parent: wid-1   # set to wid-1 as new parent of QLineEdit
delete:  wid-0                 # delete old parent

call guichange
QRadioButton                     # tmp is QRadioButton
add: QRadioButton parent: wid-2  # set to wid-2 as the parent of QRadioButton
delete:  wid-1                   # delete old parent
delete:  QLineEdit               # message printed by the lambda function 
delete:  QLineEdit               # indicating that QLineEdit has been deleted

call guichange
wrapped C/C++ object of type QLineEdit has been deleted # you want to use QLineEdit 
                                                        # but it had been removed
                                                        # previously causing 
                                                        # that error message

如果您想交换小部件,适当的选项是QStackedWidget,如下所示:

class window25(QtWidgets.QMainWindow):
    def __init__(self):
        super(window25, self).__init__()
        self.lineedit = QtWidgets.QLineEdit()
        self.checkbox = QtWidgets.QCheckBox()
        self.optBox = QtWidgets.QRadioButton()
        self.btn = QtWidgets.QPushButton("press me")
        wid = QtWidgets.QWidget()
        myLayout=QtWidgets.QVBoxLayout()
        self.stacked = QtWidgets.QStackedWidget()
        self.stacked.addWidget(self.lineedit)
        self.stacked.addWidget(self.checkbox)
        self.stacked.addWidget(self.optBox)
        wid.setLayout(myLayout) 
        myLayout.addWidget(self.btn)
        myLayout.addWidget(self.stacked)
        self.setCentralWidget(wid)
        self.guichange()
        self.btn.clicked.connect(self.guichange)

    def guichange(self):
        widget = random.choice([self.lineedit,self.checkbox,self.optBox])
        self.stacked.setCurrentWidget(widget)

if __name__ == '__main__':
    app=QtWidgets.QApplication(sys.argv)
    ex=window25()
    ex.show()
    sys.exit(app.exec_())

相关问题 更多 >