I have a simple example PyQt5
program below which creates two QPushButtons
in a loop, one for each value in a list, [ "foo", "bar" ]
It sets the clicked
slot to a lambda which prints the current list value.
It should print "foo"
when the user clicks the foo
button, and bring "bar"
when the user clicks the bar
button.
Instead, however, it prints "bar"
when clicking either.
#!/usr/bin/env python3
import sys
import subprocess
from PyQt5 import QtCore, QtWidgets
class App(QtWidgets.QWidget):
def __init__(self):
super().__init__()
layout = QtWidgets.QVBoxLayout()
self.setLayout(layout)
for i in [ 'foo', 'bar' ]:
btn = QtWidgets.QPushButton(i)
btn.clicked.connect(lambda: print(i)) # print "foo" or "bar"
layout.addWidget(btn)
qapp = QtWidgets.QApplication(sys.argv)
app = App()
app.show()
sys.exit(qapp.exec_())
The issue I'm having (I presume) is that the value of i
is reassigned on each iteration of the loop, so when the user clicks on the "foo"
button, the lambda has a reference to i
, which was subsequently set to "bar"
.
As such, every time the user clicks a button, both foo
and bar
print bar
.
I have tried using copy.copy(i)
and copy.deepcopy(i)
:
for i in [ 'foo', 'bar' ]:
i = copy.deepcopy(i)
btn = QtWidgets.QPushButton(i)
btn.clicked.connect(lambda: print(i))
layout.addWidget(btn)
Unfortunately that has no effect.
Question:
How can I get a copy of i
for use in my slot / lambda, so that subsequent iterations of my loop don't change the value in all previous iterations?