Frage zum erstellen von Radiobuttons per For Schleife

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Matil
User
Beiträge: 5
Registriert: Donnerstag 22. Januar 2009, 15:39

Hi,
Ich hab da mal ein Problem und hoffe das einer (oder mehrere :) ) mir weiter helfen kann.
Ich habe eine Liste von Strings deren länge sich erst in der Laufzeit entscheidet.
z.B.

Code: Alles auswählen

Liste = ['String1','String2',....,'StringN']
Nun lass ich per

Code: Alles auswählen

for arg in Liste:
			# Buttons
			self.radio1Button = QtGui.QRadioButton(Liste[index], self)
			self.radio1Button.setGeometry(QtCore.QRect(20, y1, 10, 10))

			QtCore.QObject.connect(self.radio1Button, QtCore.SIGNAL("clicked ()"),self.radio1ButtonClicked)

			# Label Felder
			self.label1 = QtGui.QLabel(self)
			self.label1.setGeometry(QtCore.QRect(60, y2, 150, 30))
			self.label1.setText(str(arg))

			y1=y1+40
			y2= y2+ 40
			index = index+1
Meine Radiobuttons generieren. Das funktioniert auch soweit.
Mein Problem ist jetzt das ich natürlich nicht mehr unterscheiden kann welcher der Buttons gedrückt wurde, da wenn ich versuche

Code: Alles auswählen

self.radio1Button.text()
anzusprechen er natürlich immer den letzen Wert nimmt.

Mir würde schon reichen wenn zum Schluss ne print anweisung rauskommt die in etwa ausgibt
"Hey du hast den Radiobutton nummer x mit dem Label y gedrückt".

Irgendwie komm ich da auf keine richtigen Ideen (was auch an den Temperaturen z.Z. liegen kann :| )

Ich hoffe ihr könnt mir da weiterhelfen.

lg Matil



P.S. Natürlich hab ich jetzt das initialisieren der Variablen wie y1 usw nicht mit angegeben.....das hab ich aber gemacht keine angst :)
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Ich weiß ja nicht, wie das bei Qt so ist mit den Callbacks, aber bekommt das Callback für `clicked` nicht das angeklickte Widget mit? Wenn ja, dann hast du doch da schon deinen Button.

Ansonsten macht es wenig Sinn, jeden Button an den Namen "radioButton1" zu binden. Damit bekommst du ja höchstens den zuletzt erzeugten Knopf. Mehr Sinn würde hier eine Liste oder ein Dictionary machen, je nach Datenmodell.
Shaldy
User
Beiträge: 123
Registriert: Sonntag 2. März 2008, 22:49

Die imo einfachste Möglichkeit wäre, sich die Referenz auf den geklickten Button beim Aufruf von self.buttonClicked übergeben zu lassen. Schau in der Dokumentation unter QAbstractButton nach.
Die EventHandler mousePressEvent und keyPressEvent (falls dein Ui auch über die Tastatur gesteuert werden können soll) werden dir weiterhelfen.

Code: Alles auswählen

class MyRadioButton(QtGui.QRadioButton):

         def __init__(self, parent = None):
                  QtGui.QRadioButton.__init__(self, parent)

         def mousePressEvent(self, event):
                  pass

         def keyPressEvent(self, event):
                  pass
Ist ungetestet ;)
Dies ist keine Signatur!
ichisich
User
Beiträge: 134
Registriert: Freitag 1. Januar 2010, 11:52

Hi,

in deinem Slot kannst Du mit

Code: Alles auswählen

self.sender()
an die Referenz des sendenden Objekts kommen.

Abgesehen davon ist es ratsam ein Layout für die Buttons zu nehmen an stelle von hart codierten Positionen.

Code: Alles auswählen

def buttons(self):
    
    self.verticalLayout = QtGui.QVBoxLayout(self.widget)
    self.buttonNames = ["test1", "test2", "test3"]
    for arg in self.buttonNames:
        self.b = QPushButton(arg)
        self.verticalLayout.addWidget(self.b)
        self.connect(self.b, SIGNAL("released()"), self.test)

def test(self):
    print "Button text: ", self.sender().text()
Habs jetzt halt mit QPushButtons gemacht ...
lunar

@shaldy: Oh Gott, bitte nicht. Die Eventhandler haben mit dem Problem nun überhaupt gar nichts zu tun.

An das auslösende Widget kommt man mit "self.sender()" oder in dem man partielle Funktionen als Slot verwendet:

Code: Alles auswählen

button.clicked.connect(functools.partial(self._some_slot, button))
In letzterem Fall erhält der Slot den Button als erstes Argument.
Matil
User
Beiträge: 5
Registriert: Donnerstag 22. Januar 2009, 15:39

Dauerbaustelle hat geschrieben: Ansonsten macht es wenig Sinn, jeden Button an den Namen "radioButton1" zu binden. Damit bekommst du ja höchstens den zuletzt erzeugten Knopf.

Mein Problem ist das die Buttons nicht manuel sonder automatisch erzeugt werden.
Ich weis nämlich nicht vorher wie groß meine liste ist und anhand dieser werden ja, je nach Anzahl der einträge in der Liste, die radiobuttons erstellt.

Wenn ich das problem nicht hätte, hätte ich die radiobuttons einzeln bzw unterschiedlich benannt :)


Übrigens danke für den Tipp mit

Code: Alles auswählen

self.sender()
probiere das gerade mal etwas aus. Halte euch aber auf dem neusten Stand ;)


//Edit


Superklasse :D

Es Funktioniert!!!!!
mit

Code: Alles auswählen

sender = self.sender()
text= sender.text()
print text
gibt er mir genau das aus was ich haben will.

Vielen Dank Leute
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Das Problem mit den Referenzen bleibt aber bestehen. Python verliert die Referenzen zu den vorherigen RadioButtons, da Du `self.radio1Btutton` überschreibst. Auf die Magie der Qt-internen Referenzierung würde ich mich nicht verlassen, das ist unsauber und wenig nachvollziehbar und führt mit Sicherheit an anderer Stelle zum Programmabsturz. Lösung des Problems ist es, die Buttons in Python "erreichbar" zu halten, z.B. mittels einer Liste.
lunar

@jerch: Auch in PyQt4 existieren Objekte solange wie ihr Vater-Objekt existiert. Wenn man "parent" im Konstruktor korrekt setzt, dann ist eine Referenz auf Python-Seite nicht nötig. Das ist weder magisch noch unsauber, sondern dokumentiert.
Antworten