2016-06-20 3 views
1

はの私は、ダイアログボックス、私のメインプログラムの子供を作りたいとしましょう:PyQt:ウィジェットを作成するときに親を与えますか?

from PyQt4 import QtGui, QtCore 

class WizardJournal(QtGui.QDialog): 

    def __init__(self, parent): 

     super(WizardJournal, self).__init__(parent) 

     self.parent = parent 

     self.initUI() 


    def initUI(self): 

     self.parent.wizard = QtGui.QWidget() 

     self.ok_button = QtGui.QPushButton("OK", self) 

     self.vbox_global = QtGui.QVBoxLayout(self) 

     self.vbox_global.addWidget(self.ok_button) 

     self.paret.wizard.setLayout(self.vbox_global) 
     self.parent.wizard.show() 


if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    parent = QtGui.QWidget() 
    obj = WizardJournal(parent) 
    sys.exit(app.exec_()) 

このダイアログボックスには、私のメインプログラムによって開閉されます。メモリ消費量に関して、より良い何が:

  • self.ok_button = QtGui.QPushButton("OK", self)
  • self.ok_button = QtGui.QPushButton("OK")

基本的に、私はウィジェットを作成するとき、私は親ウィジェットを言及すべきであるかどうかを知りたいと思います。このダイアログボックスを閉じると、作成時に親ウィジェットについて言及しなかった場合、OKボタンがメモリから解放されますか?

答えて

10

あなたの例が現在構造化されている方法を考えると、ダイアログやその子ウィジェットは閉じても削除されません。

あなたはこのように見えるように例の終わりを変更することで、これを見ることができます:

(ダイアログが閉じられた後に)このような出力が得られます
app.exec_() 
print('\n'.join(repr(w) for w in app.allWidgets())) 

のPyQtで
<__main__.WizardJournal object at 0x7fcd850f65e8> 
<PyQt4.QtGui.QPushButton object at 0x7fcd850f6708> 
<PyQt4.QtGui.QWidget object at 0x7fcd850f6558> 
<PyQt4.QtGui.QDesktopWidget object at 0x7fcd850f6828> 
<PyQt4.QtGui.QWidget object at 0x7fcd850f6678> 

Python側(PyQtラッパーオブジェクト)とC++側(基底のQtオブジェクト)の2種類のオブジェクトが保持されている可能性があることに注意する必要があります。オブジェクトを完全に削除するには、これらの参照をすべて削除する必要があります。

一般に、Qtは、明示的に指示しない限り、オブジェクトを削除しません。これは、親とのダイアログを作成するときに注意する必要があることです。それ以外の場合はメモリリークを生成するのが非常に簡単です。コードは次のように書かれて見ることが一般的です:一見無害に見える

def openDialog(self): 
    dialog = MyDialog(self) 
    dialog.show() 

- しかし、この方法は、新しいダイアログにそれが呼ばれるたびに作成され、およびQtは一つ一つのものに保持することになりますそのうちの(C++側のparentの参照のため)。 親を持っている必要があります

def openDialog(self): 
    self.dialog = MyDialog() 
    self.dialog.show() 

しかし、どのようなモーダルダイアログをどうする、:それだけではPython側の基準を維持するように、これを回避する1つの方法は、再書き込み方法にありますか?

class MyDialog(QtGui.QDialog): 
    def __init__(self, parent): 
     super(MyDialog, self).__init__(parent) 
     self.setAttribute(QtCore.Qt.WA_DeleteOnClose) 

そして、それが閉じているときに、今Qtが自動的にダイアログを削除し、また、再帰的にその子のすべてが同様にオブジェクトを削除します。その場合は、次のようなダイアログクラスを初期化することができます。これは空のPyQtラッパーオブジェクトを残してしまいますが、最終的にはPythonガベージコレクタによって削除されます。

は、だからあなたの特定の例のために、私はこのような何かを見て、それを再書き込みだと思う:

import sys 
from PyQt4 import QtGui, QtCore 

class WizardJournal(QtGui.QDialog): 
    def __init__(self, parent): 
     super(WizardJournal, self).__init__(parent) 
     self.setAttribute(QtCore.Qt.WA_DeleteOnClose) 
     self.initUI() 

    def initUI(self): 
     self.ok_button = QtGui.QPushButton("OK", self) 
     layout = QtGui.QVBoxLayout(self) 
     layout.addWidget(self.ok_button) 
     self.show() 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 
    parent = QtGui.QWidget() 
    obj = WizardJournal(parent) 
    app.exec_() 
    print('\n'.join(repr(w) for w in app.allWidgets())) 

ダイアログクラスは今、完全に自己完結型である、との唯一の外部Pythonの参照がありますそれのインスタンス。 (ダイアログクラス内から親ウィジェットにアクセスする必要がある場合は、self.parent()を使用できます)。

PS:ウィジェットがレイアウトに追加された場合、それらは自動的に最終的なレイアウトが含まれているものは何でもトップレベルのウィジェットに再子になります。だから、厳密に言えば、明示的にあなたのコードでこのようなウィジェットの親を設定する必要はありません。

+0

優秀な答え。クリアと説明しています。ありがとうございました。 – Rififi

関連する問題