en utilisant PyQt, j'essaie de créer une interface pour laquelle je peux ajouter ou supprimer des widgets de manière dynamique. Je veux définir une classe distincte pour le widget qui sera ajouté ou supprimé. Je n'arrive pas à obtenir le widget que j'instancie à afficher dans l'interface principale. Voici le code que j'utilise:
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_()
en réalité, lorsque j'utilise le code ci-dessous dans ma méthode 'addWidget', il fait exactement ce que je veux, mais la méthode de classe ne semble pas fonctionner.
z = QtGui.QPushButton(self.scrollAreaWidgetContents)
count = self.formLayout.rowCount())
self.formLayout.setWidget(count, QtGui.QFormLayout.LabelRole, z)
Je me demande pourquoi le z = Test () ne donne aucun résultat? Des idées? Merci!
En fait, ça marche. Le problème est que votre widget Test
a une QPushButton
sans aucune gestion de disposition. Donc, il ne peut pas calculer sa minimumSize
en prenant en compte le bouton. Lorsque vous placez ce widget dans une présentation, il se réduit simplement à 0
(puisqu'un QWidget
n'a pas de minimumSize
par défaut) et vous ne voyez rien.
Vous avez le choix entre deux possibilités: gérer manuellement la présentation et entrer dans un monde de douleur inutile ou vous faire confiance à des gestionnaires de présentation. En général, vous devriez préférer ce dernier.
Je réécrirais votre script comme ceci (bien que je ne sois pas sûr de la raison pour laquelle vous utilisez QFormLayout
, je le laisse tel quel.):
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_()
Voici un petit changement qui fera que le bouton se supprime une fois cliqué:
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_()
De cette façon, il ne devrait pas y avoir de fuite de mémoire lors de la suppression et le bouton peut en fait être utilisé pour des choses. Je suis ce modèle pour les barres de progression par dizaines pour la surveillance des téléchargements et des morceaux et cela fonctionne très bien, même avec le filetage et le traitement multiple. Et pas les QThreads faciles ...
Si tu veux dire, supprime un widget à chaque fois qu'un bouton est cliqué, ou lors de tout événement du programme ur, utilise la méthode deleteLater (): self.yourwidget.deleteLater()
self.button.clicked.connect(delete_widget);
def delete_widget(self):
self.widget.deleteLater();
self.widget.deleteLater ();
L'utilisation de la fonction ci-dessus permet à ce widget de disparaître de l'application.