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更改窗口,但我尝试了其他按下按钮的东西随机更改了mainWindow Central小部件。几次成功后(即按下按钮3,4次工作)正确")但之后我收到了错误
包装的QCheckBox类型的c / c ++对象已被删除
QLineEdit类型的包装c / c ++对象已被删除
我无法理解哪个陈述导致了这个错误以及我错误的原因或地点
答案 0 :(得分:2)
这是由Qt的实施和理念引起的,回顾了观察到的documentation:
[...]
QObjects在对象树中组织自己。当你创建一个 QObject以另一个对象作为父对象,该对象将自动生成 将自己添加到父亲的子()列表中。父母拥有所有权 对象;即,它将自动删除其中的子女 析构函数。您可以按名称查找对象,也可以选择键入 使用findChild()或findChildren()。
[...]
正如他所说,如果父母也摧毁了孩子,并且由于所有小部件都有QObject
作为他们的前任,他们也遵守这些规则。
但为什么有些小部件被破坏?
每次使用setCentralWidget()
时,先删除中央窗口小部件的对象。
CentralWidget()的子节点是什么?
当小部件附加到布局时,这些小部件被设置为使用该布局的小部件的父级。
wid = QtWidgets.QWidget()
myLayout.addWidget(tmp)
wid.setLayout(myLayout)
self.setCentralWidget(wid)
为什么没有消除QPushButton?
QPushButton
,有时与其他小部件一起发生的事情是,在使用setCentralWidget()
之前,即删除父级,它会从父级更改:
myLayout=QtWidgets.QVBoxLayout() # some parent
myLayout.addWidget(self.btn) # a new parent is established
[...]
self.setCentralWidget(wid) # elimination of the old parent
最后,我将使用以下代码解释一个随机示例:
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_())