I just upgraded PySide6 (PySide6==6.6.0 from 6.2.2) and a new behavior is wreaking havoc with my GUI program. Every place where I have a clicked
signal, the hooked up slot is receiving an extra bool==False argument.
x = QPushButton('New', clicked = self.new_append_title)
# ..... add x to my gui
def new_append_title(self, *args, **kwargs):
print(f' Args: {args}' )
print(f' Kwargs: {kwargs}' )
This returns
Args: (False,)
Kwargs: {}
Previously with earlier versions I was getting no arguments. I can fix all my code so it takes an extra dummy argument, but does anybody know what is going on here? I also updated a few other things in my requirements - like moving to python 3.12, so it might not be a PySide issue...
In response to ekhumoro I am actually trying to send and argument here. I have tried every permutation I can think of, including the one he gives in his answer below.
self.save_button.clicked.connect(lambda *, row=row: self.save_row(row))
def save_row(self, row):
print(f'row={row})
Finally worked. I am not clear on what * does, but it seems to hold the arg from qPushButton signal and therefore it is not necessary to have it in the member function.
I can indeed reproduce this odd difference in behaviour between various versions of PySide. However, unlike my previous answer on this topic, the current issue relates to how the signal connections are made. It seems PySide has been highly inconsistent in this regard, whereas PyQt is much more reliable (at least in the few versions I tested with).
The important difference with the current case, is that signal connections made via the
clicked
keyword argument, do not behave the same way as explicit connections made via theconnect
method. The whole sorry mess is detailed below, but the immediate take-home message here is this: to future-proof your PySide code, do not ever rely on default signal arguments being silently dropped. Always assume that some future version will start sending the default arguments, and protect your slots accordingly. This is how PyQt5/6 has always behaved, and it seems likely that PySide6 will eventually do likewise. In my own code, I have most commonly employed keyword-only arguments to work-around this issue, like this:As you will see below, this behaves the same way across all versions of PySide and PyQt I tested, and is possibly the least intrusive in terms of API changes and general code-churn. (But see also my previous answer for several other options - with some provisos).
Now for the gory details.
Below is a test script that exposes the problems. As you will see from the output, both PySide2 and PySide6 show different behaviour depending on how the signal connection is made, and on the precise version used. The good news is that PySide-6.6.0 shows the same behaviour as PyQt5/6 when making connections via the
clicked
keyword argument. The bad news is that usingconnect
shows the same inconsistent behaviour as PySide2. Note also that PySide2 itself shows some differences in how slot arguments are treated: when usingconnect(slot)
, the first argument is over-written, whereas withclicked=slot
, it isn't.TEST SCRIPT:
OUTPUT:
PySide2:
PySide6:
PyQt5/6: