25

如果我运行此代码:

    #!/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 应该保持对它的引用。我已经彻底调查了这些帖子: Understanding the "underlying C/C++ object has been deleted" 错误 Can a PyQt4 QObject be queried to determine if the underlying C++ instance has been destroyed?

为什么按钮被删除?

4

4 回答 4

21

这个问题的答案可以在这里找到: Python PySide (Internal c++ Object Already Deleted)

显然,使用 setCentralWidget 将一个小部件分配给 QMainWindow,然后使用 setCentralWidget 分配另一个小部件将导致底层 c++ QWidget 被删除,即使我有一个维护对它的引用的对象。

注意:QMainWindow 拥有小部件指针的所有权并在适当的时候将其删除。

于 2013-07-29T23:05:17.040 回答
3

Brain的回答完美地解释了这个问题。这个链接更详细地解释了事情。

我对这个问题的解决方案是将小部件设置为对象的属性(例如,只需在类方法中使用self.label = ...而不是)。label = ...您可能希望对附加到小部件的任何布局执行相同操作。

通过这种方式,您可以创建小部件的副本,以便在发生 C++ 内存清理时,您仍然拥有对该小部件的引用。

希望这可以帮助。

于 2018-01-12T07:07:07.090 回答
1

当您运行连续线程并关闭主窗口/对话框而不先关闭线程但在后台线程正在处理时,此问题也会出现在 PyQT5 中。当您再次打开窗口时,第二个线程会生成并删除预先存在的小部件。您需要先退出线程,然后再重新运行它。您可以通过在主窗口/对话框中检查任何小部件的可见性来退出线程

            **if self.widget.isVisible() == False:
                break**
于 2020-03-16T05:11:54.667 回答
1

在另一种情况下,解决方案是首先将所有子对象添加到分离布局中,然后将布局添加到父布局中作为最后一步。那是:

    l = QGridLayout()
    l.addWidget(QLabel("child1"), 0, 0)
    l.addWidget(QLabel("child2"), 0, 1)
    ...
    parentLayout.addLayout(l)
于 2019-01-23T04:36:15.810 回答