Issue
I have a similar problem to Using lambda expression to connect slots in pyqt. In my case, I want to send two different pieces of information. Which button is being clicked (the port number) and the sensor associated with that port number (stored in a QComboBox).
This is what I want to achieve and this works fine:
self.portNumbers[0].clicked.connect(lambda: self.plot(1, self.sensorNames[0].currentText()))
self.portNumbers[1].clicked.connect(lambda: self.plot(2, self.sensorNames[1].currentText()))
self.portNumbers[2].clicked.connect(lambda: self.plot(3, self.sensorNames[2].currentText()))
...
But when I put this in a loop as this:
for i, (portNumber, sensorName) in enumerate(zip(self.portNumbers, self.sensorNames)):
portNumber.clicked.connect(lambda _, x=i + 1, y=sensorName.currentText(): self.plot(x, y))
I get the correct port numbers but the change in the Combo box is not reflected.
Minimum reproducible code:
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QComboBox
portNumbers = [None] * 8
sensorNames = [None] * 8
SENSORS = ["Temperature", "Pressure", "Height"]
class MyWidget(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
self.connectButtonsToGraph()
def init_ui(self):
vbox = QVBoxLayout()
h1box = QHBoxLayout()
h2box = QHBoxLayout()
for i, (portNumber, sensorName) in enumerate(zip(portNumbers, sensorNames)):
# Set portNumber as pushButton and list sensorNames in ComboBox
portNumber = QPushButton()
sensorName = QComboBox()
h1box.addWidget(portNumber)
h2box.addWidget(sensorName)
# Give identifier, text info to individual ports and modify the list
portNumberName = "port_" + str(i + 1)
portNumber.setObjectName(portNumberName)
portNumberText = "Port " + str(i + 1)
portNumber.setText(portNumberText)
portNumbers[i] = portNumber
# Add the textual information in PushButton and add modify the list
sensorNameStringName = "portSensorName_" + str(i + 1)
sensorName.setObjectName(sensorNameStringName)
for counter, s in enumerate(SENSORS):
sensorName.addItem("")
sensorName.setItemText(counter, s)
sensorNames[i] = sensorName
vbox.addLayout(h1box)
vbox.addLayout(h2box)
self.setLayout(vbox)
self.show()
def connectButtonsToGraph(self):
for i, (portNumber, sensorName) in enumerate(zip(portNumbers, sensorNames)):
portNumber.clicked.connect(lambda _, x=i + 1, y=sensorName.currentText(): self.plot(x, y))
def plot(self, portNumber, sensorName):
print(portNumber, sensorName)
def run():
app = QApplication([])
mw = MyWidget()
app.exec_()
if __name__ == '__main__':
run()
Solution
Thank you, @musicamante, for the explanation. I am just adding it in the answer to mark it as solved if someone has similar issues.
As they mentioned, the value of the keyword argument of lambda is evaluated when it's created. So, creating a reference to sensorName.currentText()
used the value of the current text at that time. But creating a reference to the ComboBox itself allowed for getting the value of the text in run-time.
Answered By - linkingashu
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.