PyQt:RuntimeError:包装的C / C ++对象已被删除

时间:2013-07-29 01:54:46

标签: garbage-collection pyqt pyqt4 qobject qmainwindow

如果我运行此代码:

    #!/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

我不明白为什么要删除该对象。窗口应该保持对它的引用。 我已经彻底调查了这些帖子: 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?

为什么按钮被删除?

4 个答案:

答案 0 :(得分:14)

这个问题的答案如下: Python PySide (Internal c++ Object Already Deleted)

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

  

注意:QMainWindow获取小部件指针的所有权并在适当的时候删除它。

答案 1 :(得分:0)

Brain的答案完美地解释了这个问题。 This Link更详细地解释了一些事情。

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

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

希望这有帮助。

答案 2 :(得分:0)

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

public class Feed {

    @SerializedName("id")
    @Expose
    private String id;
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @SerializedName("Feeds_Header")
    @Expose
    private String Feeds_Header;
    public String getFeeds_Header() {
        return Feeds_Header;
    }

    public void setFeeds_Header(String feedsHeader) {
        this.Feeds_Header = feedsHeader;
    }

    @SerializedName("Feeds_Date")
    @Expose
    private String Feeds_Date;
    public String getFeeds_Date() {
        return Feeds_Date;
    }

    public void setFeeds_Date(String feedsDate) {
        this.Feeds_Date = feedsDate;
    }

}

答案 3 :(得分:-1)

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

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