PyQt: RuntimeError: объект C/C++ в оболочке удален

Если я запускаю этот код:

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

Я не понимаю, почему объект удаляется. Окно должно поддерживать ссылку на него. Я тщательно исследовал эти сообщения: понимание" базовый объект C/C++ был удален " ошибка можно ли запросить QObject PyQt4, чтобы определить, был ли уничтожен базовый экземпляр c++?

почему кнопка удалили?

2 ответов


этот ответ на этот вопрос находится здесь: Python PySide (внутренний объект c++ уже удален)

по-видимому, назначение одного виджета QMainWindow с помощью setCentralWidget, а затем назначение другого виджета с setCentralWidget приведет к удалению базового c++ QWidget, даже если у меня есть объект, который поддерживает ссылку на него.

Примечание: QMainWindow берет на себя ответственность за указатель виджета и удаляет его на соответствующее время.


ответ мозга прекрасно объясняет проблему. Этой Ссылке объясню все более подробно.

моим решением этой проблемы было установить виджеты в качестве атрибутов объекта (например, просто используя self.label = ... вместо label = ... в методах класса). Возможно, вы захотите сделать то же самое для любых макетов, прикрепленных к виджету.

таким образом, вы создаете копию виджета, чтобы при очистке памяти C++ у вас все еще была ссылка на штучка.

надеюсь, что это помогает.