Mit einer lambda-Ausdruck zu verbinden slots in pyqt
Ich versuche zu verbinden slots mit lambda-Funktionen, es ist aber nicht so funktioniert, wie ich erwarte. In dem code unten, habe ich erfolgreich, in Verbindung mit den ersten beiden Tasten korrekt. Für das zweite zwei, denen ich eine Verbindung in einer Schleife, das geht schief. Jemand vor mir hatte die gleiche Frage (Qt - Connect-slot mit Parameter mit lambda), aber diese Lösung funktioniert nicht für mich. Ich habe starrte auf meinen Bildschirm für eine halbe Stunde, aber ich kann nicht herausfinden, wie mein code ist anders.
class MainWindow(QtGui.QWidget):
def __init__(self):
super(QtGui.QWidget, self).__init__()
main_layout = QtGui.QVBoxLayout(self)
# Works:
self.button_1 = QtGui.QPushButton('Button 1 manual', self)
self.button_2 = QtGui.QPushButton('Button 2 manual', self)
main_layout.addWidget(self.button_1)
main_layout.addWidget(self.button_2)
self.button_1.clicked.connect(lambda x:self.button_pushed(1))
self.button_2.clicked.connect(lambda x:self.button_pushed(2))
# Doesn't work:
self.buttons = []
for idx in [3, 4]:
button = QtGui.QPushButton('Button {} auto'.format(idx), self)
button.clicked.connect(lambda x=idx: self.button_pushed(x))
self.buttons.append(button)
main_layout.addWidget(button)
def button_pushed(self, num):
print 'Pushed button {}'.format(num)
Drücken der beiden ersten Tasten Erträge 'Gedrückt Taste 1" und "Geschoben-Taste 2', die anderen beiden sowohl Ausbeute "gedrückte Taste "False", obwohl ich erwartete, 3 und 4.
Ich auch noch nicht verstanden lambda-Mechanismus komplett. Was genau angeschlossen wird? Ein Zeiger auf eine Funktion, die erzeugt wird durch die lambda (mit dem parameter ersetzt werden) oder ist die lambda-Funktion immer dann ausgewertet, wenn das signal feuert?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
QPushButton.clicked
signal emittiert ein argument, das zeigt den Zustand der Taste. Wenn Sie die Verbindung zu Ihrem lambda-slot, das optionale argument weisen Sieidx
ist, überschrieben wird, indem der Status der Schaltfläche.Stattdessen, machen Sie Ihre Verbindung so
Diese Weise den Status der Schaltfläche wird ignoriert, und der richtige Wert übergeben, Ihre Methode.
clicked
signal, dieses signal hat eine Signatur, die beschrieben wird, hier. Wie Sie sehen können, wenn das signal emittiert wird, ein argument angegeben wird, enthält den Zustand des Buttons (oder nicht, ob der button aktiviert ist). Die variable in meinem code aufgerufen werden können, was Sie wollen, aber es muss sein, es gibt so, dass Qt nicht überschreiben das nächste argument (x=idx
) mit aktivierten Zustand.Achtung! Sobald Sie die Verbindung zwischen Ihrem signal zu einer lambda-slot mit einem Verweis auf sich selbst, Ihre widget werden nicht garbage-collected! Das ist, weil die lambda erzeugt eine Schließung mit einem weiteren uneinbringlichen Referenz auf das widget.
Somit selbst.someUIwidget.someSignal.connect(lambda p: sich selbst.someMethod(p)) ist sehr böse 🙂
lambda
gehtself
einige externe Funktion:self.someUIwidget.someSignal.connect(lambda someNonSelfMethod(self))
QObject.sender()
Methode. Darüber hinaus können Sie speichern Informationen in der widget-Eigenschaften und greifen Sie in die slot-Funktion, siehe dieses Beispiel: stackoverflow.com/questions/49446832/...Ich bin ehrlich gesagt nicht sicher, was falsch läuft mit der Verwendung von lambda-hier entweder. Ich denke, es ist weil idx (deine loop-index, wenn Sie die Tasten "auto") wird der Umfang und enthalten nicht den richtigen Wert mehr.
Aber ich glaube nicht, dass Sie brauchen, um es zu tun auf diese Weise. Wie es aussieht, der einzige Grund, warum man mit einer lambda ist, so dass Sie übergeben ein argument button_pushed(), identifizieren, welche Taste es war. Es gibt eine Funktion
sender()
genannt werden kann, in der button_pushed () - slot, die angibt, welche Taste stammt das signal.Hier ist ein Beispiel, das glaube ich nicht mehr oder weniger, was Sie für schossen: