web-dev-qa-db-ja.com

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++オブジェクトが削除されました」エラーを理解するPyQt4 QObjectを照会して、基になるC++インスタンスが破棄されたかどうかを判断できますか? ==

ボタンが削除されるのはなぜですか?

16
Brian

この質問に対するこの回答は次のとおりです。 Python PySide(内部c ++オブジェクトはすでに削除されています)

どうやら、setCentralWidgetを使用して1つのウィジェットをQMainWindowに割り当ててから、setCentralWidgetを使用して別のウィジェットを割り当てると、参照を維持するオブジェクトがある場合でも、基になるc ++ QWidgetが削除されます。

注:QMainWindowはウィジェット・ポインターの所有権を取得し、適切なタイミングでそれを削除します。

16
Brian

脳の答えは問題を完全に説明しています。 このリンク 物事をより詳細に説明します。

この問題に対する私の解決策は、ウィジェットをオブジェクトの属性として設定することでした(たとえば、クラスメソッドでself.label = ...の代わりにlabel = ...を使用するだけです)。ウィジェットにアタッチされているレイアウトについても同じことを行うことができます。

このようにして、ウィジェットのコピーを作成し、C++メモリのクリーンアップが発生したときに、ウィジェットへの参照を保持できるようにします。

お役に立てれば。

2
Ankit Bindal

別のケースでは、解決策は、最初にすべての子オブジェクトをデタッチされたレイアウトに追加し、最後のステップとしてレイアウトを親レイアウトに追加することでした。あれは:

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