pyQtを使用して、ウィジェットを動的に追加または削除できるインターフェースを作成しようとしています。追加または削除されるウィジェット用に別のクラスを定義したい。インスタンス化したウィジェットをメインインターフェース内に表示することができないようです。これが私が使用しているコードです:
from PyQt4 import QtGui, QtCore
import sys
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
# central widget
self.centralWidget = QtGui.QWidget(self)
# main layout
self.vLayout = QtGui.QVBoxLayout(self.centralWidget)
# main button
self.pButton_add = QtGui.QPushButton(self.centralWidget)
self.pButton_add.setText('button to add other widgets')
# scroll area
self.scrollArea = QtGui.QScrollArea(self.centralWidget)
self.scrollArea.setWidgetResizable(True)
# scroll area widget contents
self.scrollAreaWidgetContents = QtGui.QWidget(self.scrollArea)
# scroll area widget contents - layout
self.formLayout = QtGui.QFormLayout(self.scrollAreaWidgetContents)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
# add all main to the main vLayout
self.vLayout.addWidget(self.pButton_add)
self.vLayout.addWidget(self.scrollArea)
# set central widget
self.setCentralWidget(self.centralWidget)
# connections
self.pButton_add.clicked.connect(self.addWidget)
def addWidget(self):
z = Test(self.scrollAreaWidgetContents)
count = self.formLayout.rowCount()
self.formLayout.setWidget(count, QtGui.QFormLayout.LabelRole, z)
class Test(QtGui.QWidget):
def __init__( self, parent):
super(Test, self).__init__(parent)
self.pushButton = QtGui.QPushButton(self)
app = QtGui.QApplication(sys.argv)
myWidget = Main()
myWidget.show()
app.exec_()
問題は、以下のコードを 'addWidget'メソッド内で使用すると、まさにそれが実行したいことを実行しますが、クラスメソッドが機能していないようです。
z = QtGui.QPushButton(self.scrollAreaWidgetContents)
count = self.formLayout.rowCount())
self.formLayout.setWidget(count, QtGui.QFormLayout.LabelRole, z)
なぜz = Test()が結果を出さないのでしょうか?何か案は?ありがとう!
実際には、機能します。問題は、あなたのTest
ウィジェットにQPushButton
があり、レイアウト管理がないことです。したがって、ボタンを考慮に入れてminimumSize
を計算することはできません。そのウィジェットをレイアウトに配置すると、ウィジェットは0
に縮小されます(QWidget
にはデフォルトminimumSize
がないため)。何も表示されません。
2つの選択肢があります。手動でレイアウトを管理し、不必要な苦痛の世界に入るか、またはレイアウトマネージャーに依存します。一般に、後者を優先する必要があります。
スクリプトを次のように書き直します(QFormLayout
を使用する理由はわかりませんが、そのままにしておきます)。
from PyQt4 import QtGui, QtCore
import sys
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
# main button
self.addButton = QtGui.QPushButton('button to add other widgets')
self.addButton.clicked.connect(self.addWidget)
# scroll area widget contents - layout
self.scrollLayout = QtGui.QFormLayout()
# scroll area widget contents
self.scrollWidget = QtGui.QWidget()
self.scrollWidget.setLayout(self.scrollLayout)
# scroll area
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.scrollWidget)
# main layout
self.mainLayout = QtGui.QVBoxLayout()
# add all main to the main vLayout
self.mainLayout.addWidget(self.addButton)
self.mainLayout.addWidget(self.scrollArea)
# central widget
self.centralWidget = QtGui.QWidget()
self.centralWidget.setLayout(self.mainLayout)
# set central widget
self.setCentralWidget(self.centralWidget)
def addWidget(self):
self.scrollLayout.addRow(Test())
class Test(QtGui.QWidget):
def __init__( self, parent=None):
super(Test, self).__init__(parent)
self.pushButton = QtGui.QPushButton('I am in Test widget')
layout = QtGui.QHBoxLayout()
layout.addWidget(self.pushButton)
self.setLayout(layout)
app = QtGui.QApplication(sys.argv)
myWidget = Main()
myWidget.show()
app.exec_()
クリックするとボタンが自動的に削除されるようにする小さな変更を次に示します。
from PyQt4 import QtGui, QtCore
import sys
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
# main button
self.addButton = QtGui.QPushButton('button to add other widgets')
self.addButton.clicked.connect(self.addWidget)
# scroll area widget contents - layout
self.scrollLayout = QtGui.QFormLayout()
# scroll area widget contents
self.scrollWidget = QtGui.QWidget()
self.scrollWidget.setLayout(self.scrollLayout)
# scroll area
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.scrollWidget)
# main layout
self.mainLayout = QtGui.QVBoxLayout()
# add all main to the main vLayout
self.mainLayout.addWidget(self.addButton)
self.mainLayout.addWidget(self.scrollArea)
# central widget
self.centralWidget = QtGui.QWidget()
self.centralWidget.setLayout(self.mainLayout)
# set central widget
self.setCentralWidget(self.centralWidget)
def addWidget(self):
self.scrollLayout.addRow(TestButton())
class TestButton(QtGui.QPushButton):
def __init__( self, parent=None):
super(TestButton, self).__init__(parent)
self.setText("I am in Test widget")
self.clicked.connect(self.deleteLater)
app = QtGui.QApplication(sys.argv)
myWidget = Main()
myWidget.show()
app.exec_()
これにより、削除時にメモリリークが発生することはなく、ボタンは実際に使用できます。私は、ダウンロードとチャンクの監視について、進行状況バーのこのパターンを数十ずつ追跡し、スレッド化とマルチ処理でも問題なく動作します。簡単なQThreadsではありません...
ボタンを押すたびに、またはプログラムのイベント中にウィジェットを削除したい場合は、deleteLater()メソッドを使用します:self.yourwidget.deleteLater()
self.button.clicked.connect(delete_widget);
def delete_widget(self):
self.widget.deleteLater();
self.widget.deleteLater();
上記の関数を使用すると、ウィジェットがアプリケーションから消えます