如果我运行以下代码:
#!/usr/local/bin/ python3
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Window(QMainWindow):
def __init__(self):
super().__init__()
self.button1 = QPushButton("1")
self.button2 = QPushButton("2")
self.setCentralWidget(self.button1)
self.button1.clicked.connect(lambda: self.setCentralWidget(self.button2))
self.button2.clicked.connect(lambda: self.setCentralWidget(self.button1))
self.show()
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
window = Window()
sys.exit(app.exec_())
我得到这个输出:
Traceback (most recent call last):
File "test.py", line 16, in <lambda>
self.button2.clicked.connect(lambda: self.setCentralWidget(self.button1))
RuntimeError: wrapped C/C++ object of type QPushButton has been deleted
我不明白为什么要删除这个对象。Window应该维护对它的引用。我已经彻底调查了这些帖子:理解"底层C/C++对象已被删除"错误是否可以查询PyQt4 QObject以确定底层C++实例是否已被破坏?
为什么要删除按钮?
这个问题的答案如下:Python PySide(内部c++对象已删除)
显然,使用setCentralWidget将一个小部件分配给QMainWindow,然后使用setCentral widget分配另一个小组件将导致底层的c++QWidget被删除,即使我有一个对象维护对它的引用。
注意:QMainWindow拥有小部件指针的所有权,并在适当的时候将其删除。
当您运行连续线程并关闭主窗口/对话框而不首先关闭线程,但在后台线程正在处理时,PyQT5中也会出现此问题。当您再次打开窗口时,第二个线程会生成并删除预先存在的小部件。在重新运行之前,您需要先退出线程。您可以通过在主窗口/对话框中检查任何小部件的可见性来退出线程
**if self.widget.isVisible() == False:
break**
Brain的回答完美地解释了这个问题。这个链接更详细地解释了事情。
我对这个问题的解决方案是将小部件设置为对象的属性(例如,在类方法中简单地使用self.label = ...
而不是label = ...
)。您可能希望对附加到小部件的任何布局执行相同的操作。
通过这种方式,您可以创建小部件的副本,这样当C++内存清理发生时,您仍然可以引用该小部件。
希望这能有所帮助。
在另一种情况下,解决方案是先将所有子对象添加到分离的布局中,然后将布局添加到父布局中作为最后一步。即:
l = QGridLayout()
l.addWidget(QLabel("child1"), 0, 0)
l.addWidget(QLabel("child2"), 0, 1)
...
parentLayout.addLayout(l)
wxPython&PyPubSub:
对于那些在wxPython和PyPubSub中出现相同错误的人,请在以下位置查找解决方案:
定义wx。wxpython 中的面板析构函数
以及非零()方法。