pyqt中使用lambda表达式连接槽并发送多个值
Using lambda expression to connect slots and send multiple values in pyqt
我遇到了与 类似的问题。就我而言,我想发送两条不同的信息。单击哪个按钮(端口号)以及与该端口号关联的传感器(存储在 QComboBox 中)。
这就是我想要实现的并且效果很好:
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()))
...
但是当我把它放在一个循环中时:
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))
我得到了正确的端口号,但组合框中的更改没有反映出来。
最小可重现代码:
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()
谢谢@musicamante 的解释。如果有人遇到类似问题,我只是将其添加到答案中以将其标记为已解决。
正如他们提到的,lambda 的关键字参数的值是在创建时计算的。因此,创建对 sensorName.currentText()
的引用使用了当时当前文本的值。但是创建对 ComboBox 本身的引用允许获取 run-time.
中文本的值
我遇到了与
这就是我想要实现的并且效果很好:
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()))
...
但是当我把它放在一个循环中时:
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))
我得到了正确的端口号,但组合框中的更改没有反映出来。
最小可重现代码:
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()
谢谢@musicamante 的解释。如果有人遇到类似问题,我只是将其添加到答案中以将其标记为已解决。
正如他们提到的,lambda 的关键字参数的值是在创建时计算的。因此,创建对 sensorName.currentText()
的引用使用了当时当前文本的值。但是创建对 ComboBox 本身的引用允许获取 run-time.