2013-07-29 3 views
8

Если я запускаю этот код: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 

Я не понимаю, почему объект удаляется. Окно должно содержать ссылку на него. я тщательно исследовал эти сообщения: 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?

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

+1

У меня была аналогичная проблема с подклассом QWidget, и выяснилось, что проблема заключалась в том, что я забыл вызвать '__init__' QWidget в начале моего' __init__'. Трикси. – spookypeanut

ответ

9

Ответ на этот вопрос, как здесь: Python PySide (Internal c++ Object Already Deleted)

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

Note: QMainWindow takes ownership of the widget pointer and deletes it at the appropriate time.

0

Ответ на мозг прекрасно объясняет проблему. This Link более подробно объясните ситуацию.

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

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

Надеюсь, это поможет.