【问题标题】:PyQt: RuntimeError: wrapped C/C++ object has been deletedPyQt:RuntimeError:包装的 C/C++ 对象已被删除
【发布时间】:2013-07-28 16:58:24
【问题描述】:

如果我运行这段代码:

    #!/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” error Can a PyQt4 QObject be queried to determine if the underlying C++ instance has been destroyed?

为什么按钮会被删除?

【问题讨论】:

  • 我在 QWidget 的子类中遇到了类似的问题,结果问题是我忘记在我的 __init__ 开头调用 QWidget 的 __init__。诡计多端。
  • 在我们的例子中,调用a.call_some_parent_method(),其中a = QObjectA(parent=QObjectB()),引发了RuntimeError: wrapped C/C++ object of type QObjectA has been deleted。然而,实际原因竟然是QObjectB 类型的包装对象已被删除(不是错误消息中提到的QObjectA)。解决方案是保留对QObjectB 的引用:b = QObjectB(); a = QObjectA(parent=b)(使用 Python 2.7,PyQt5)

标签: garbage-collection pyqt pyqt4 qobject qmainwindow


【解决方案1】:

此问题的答案可在此处找到: Python PySide (Internal c++ Object Already Deleted)

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

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

【讨论】:

    【解决方案2】:

    Brain 的回答完美地解释了这个问题。 This Link详细解释。

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

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

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

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

          l = QGridLayout()
          l.addWidget(QLabel("child1"), 0, 0)
          l.addWidget(QLabel("child2"), 0, 1)
          ...
          parentLayout.addLayout(l)
      

      【讨论】:

        【解决方案4】:

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

                    **if self.widget.isVisible() == False:
                        break**
        

        【讨论】:

          猜你喜欢
          • 2020-06-01
          • 1970-01-01
          • 2021-10-03
          • 2020-11-10
          • 1970-01-01
          • 2021-06-02
          • 2019-06-05
          • 2020-08-29
          • 1970-01-01
          相关资源
          最近更新 更多