Reputation: 29
I'm working on a PySide6 application that uses a loop to create a number of pushbuttons and assign each a click event handler which is obtained by calling a static function in the loop and passing to it the pushbutton generated in that loop iteration. That static function prints the text of the pushbutton passed to it. Therefore clicking on each button is supposed to print its text. But it always prints the same string, the text of the button created in the first iteration of the loop ('Button 0'). This is a sample code that produces the mentioned effect.
import sys
from PySide6.QtCore import QSize
from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QDialog
def get_button_click(x):
def click():
print(x.text())
return click
class MainWindow(QDialog):
def __init__(self):
super().__init__()
verticalLayout = QVBoxLayout(self)
for i in range(5):
button = QPushButton('Button {}'.format(i))
button.clicked.connect(get_button_click(button))
verticalLayout.addWidget(button)
self.setFixedSize(QSize(400, 300))
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
I tried static and object functions, but the results were the same. Defining a default parameter as
def get_button_click(x):
def click(x=x):
print(x.text())
return click
results in AttributeError: 'bool' object has no attribute 'text'
I searched the web extensively and found nothing similar.
This post illustrate the concept of defining functions in a loop.
This is the same with PySide2.
I wonder if this is a bug or designed?
And if there is any workaround?
Much appreciated
Upvotes: 0
Views: 52
Reputation: 29
Till the availability of a fixed version a dirty fix is to wrap the inner function in an exec statement and return the locals with the key of that function
def get_button_click(x):
exec(f'def click(): print({x})')
return locals()['click']
Upvotes: -1