bel. Anzahl von Widgets zur Laufzeit erzeugen, wie?

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
EmaNymton
User
Beiträge: 174
Registriert: Sonntag 30. Mai 2010, 14:07

Bisher waren meine Oberflächen statisch, so dass ich sie mit dem Designer zusammenstellen konnte.

Jetzt möchte ich gerne ein Fenster erzeugen, dass aus mehreren Bausteinen der Form

Label HorizontalSlider LineEdit

bestehen, die untereinander angeordnet werden sollen. Die Anzahl ist jedoch variable, d. h. ich kann das erst zu Laufzeit entscheiden, wie viele dieser Bausteine ich brauche.

Wie stellt man das am Besten an?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du kannst diese Komponente ja im Designer als Kind von QWidget zusammenklicken uns peichern.

In Deinem Script und dem dortigen MainWindow (oder was Du da hast) initialisierst Du dann einfach in einer Schleife oder nach einer Aktion ein neues Exemplar und speicherst es z.B. in einer Liste. Auf jeden Fall solltest Du das Widget, in dem Du die Komponente anzeigst auch als parent der Komponente setzen.

Generell wäre es aber auch eine Überlegung, einen entsprechenden View um diese Eingabemöglichkeiten und Darstellungen zu erweitern, also etwa einen QListView.

Iirc hatte Lunar genau dazu mal ein Beispiel gestrickt, bei dem ein LineEdit und Button in einem ListView integriert wurden.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
EmaNymton
User
Beiträge: 174
Registriert: Sonntag 30. Mai 2010, 14:07

Vielen Dank, habe es so wie vorgeschlagen hinbekommen. Trotzdem habe ich das Gefühl, dass es auch eleganter geht.
Ich sehe mich noch als Anfänger in Python, deswegen hätte ich gerne eine kurze Rückmeldung, was man besser machen könnte oder ob das so richtig ist.

Die Klasse, die das Widget erzeugen soll, sieht so aus

Code: Alles auswählen

class SliderWidget(QtGui.QWidget):
    def __init__(self,labelText=QtCore.QString(),wert=1,parent=None):
        super(SliderWidget, self).__init__(parent)
        self.label = QtGui.QLabel(labelText)
        self.label.setMinimumSize(QtCore.QSize(150, 60))
        self.label.setMaximumSize(QtCore.QSize(150, 60))
        self.horizontalLayout = QtGui.QHBoxLayout()
        self.horizontalLayout.addWidget(self.label)
        self.horizontalSlider = QtGui.QSlider()
        self.horizontalSlider.setMinimumSize(QtCore.QSize(470, 60))
        self.horizontalSlider.setMaximumSize(QtCore.QSize(470, 60))
        self.horizontalSlider.setMaximum(10)
        self.horizontalSlider.setPageStep(1)
        self.horizontalSlider.setValue(wert)
        self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal)
        self.horizontalLayout.addWidget(self.horizontalSlider)
        self.lineEdit = QtGui.QLineEdit()
        self.lineEdit.setMinimumSize(QtCore.QSize(60, 60))
        self.lineEdit.setMaximumSize(QtCore.QSize(60, 60))
        self.lineEdit.setText(str(wert))
        self.horizontalLayout.addWidget(self.lineEdit)
        self.setLayout(self.horizontalLayout)

    def getSlider(self):
        return self.horizontalSlider

    def getLineEdit(self):
        return self.lineEdit

    def getLabel(self):
        return self.label
Mein Problem war nachher die Signale vom horizontalSlider zu connecten, da in der Liste ja nachher Objekte vom Typ SliderWidget stehen, ich also auf den Slider eines jeden Widgets zugreifen muss. Deswegen die drei Rückgabemethoden, die das jeweilige Objekt zurückgeben.

Das connecten sieht dann folgendermaßen aus

Code: Alles auswählen

        self.sliderWidget = SliderWidget('test',1,self.scrollAreaWidgetContents)
        slider = self.sliderWidget.getSlider()
        self.connect(slider,QtCore.SIGNAL("valueChanged(int)"),self.sliderBewegt)
Nun hatte ich das Problem, dass ich ja in der Methode sliderBewegt() nichts mehr vom zugehörigen Widget weiß. Ich habe mir jetzt so beholfen, dass ich die Methode sender() und parentWidget() verwendet habe. Das sieht dann in der Testversion folgendermaßen aus

Code: Alles auswählen

def sliderBewegt(self,i):
       print self.sender().parentWidget().getLabel().text(), self.sender().parentWidget().getSlider().value()
       self.sender().parentWidget().getLineEdit().setText(str(i))
Wie gesagt, die Zeilen in sliderBewegt geben mir ein Gefühl, dass es auch einfacher geben muss, aber mir fehlt einfach die Idee, wie.

Wäre schön, wenn jemand die Zeit fände, mir einen Tipp zu geben.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Lies Dir mal diesen Thread durch. Das ist im Prinzip das gleiche.

Außerdem lernst Du da gleich die "neue" connect-Syntax kennen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten