Role of 'is_checked' , PySide 6 e-book, listing 7

Hi All,

I am currently studying Martin’s e-book in the PySide 6 edition. Everything seemed pretty clear until I arrived at chapter 4, listing 7, on signals and slots.
That’s where the confusion struck.

How does the method ‘the_button_was_toggled’ check if the button is in the checked state? What is the role of ‘is_checked’? Is it a parameter to pass a value ‘into’ the method, or to get a value ‘from’ it?

I searched the documentation for ‘is_checked’ but found nothing, except that ‘checked’ is a method of the QAction class.
And when I changed ‘is_checked’ to ‘x’, the script still worked! :face_with_spiral_eyes:

If anyone could explain what exactly is happening here, that would be great!

Thanks in advance,
Erik

Hi @Erik
this is_checked it just parameter name pass by internals of Qt/PySide6.

So, with line:

button.clicked.connect(self.the_button_was_toggled)

you subscribe in Qt internals for notification when button will be clicked please run method the_button_was_toggled() and pass all needed parameters.

Note: is_checked is optional, you can remove it and code run fine, but Qt sending notification expect that callback has correct signature in this case one optional parameter (name is not important), but when you changed to:

    def the_button_was_toggled(self, is_checked, other):
        print("Checked?", is_checked, other)

code will fail with in a bit misleading way:

TypeError: MainWindow.the_button_was_toggled() missing 2 required positional arguments: ‘is_checked’ and ‘other’

General it means signature is wrong.

Diffrent events of other widgets require other set of parameters i.e. currentCellChanged of QTableWidget require 4 parameters:

self.tw_gkeys = QTableWidget()
self.tw_gkeys.currentCellChanged.connect(self._current_cell)

def _current_cell(self, currentRow: int, currentColumn: int, previousRow: int, previousColumn: int):
    print(currentRow, currentColumn, previousRow, previousColumn)

Hi Michal,

Thanks for your explanation & sorry for my delayed response! Long story short: I tried to login to the forum using my iPad, which didn’t work. I couldn’t remember what email address I had entered either, so “forgot password” was of no use. :man_facepalming:
Then I suddenly remembered I had posted this question using my laptop, which remembered the password I had forgotten. :sweat_smile:

On topic:
While your explanation certainly helps, I still cannot get my head fully around it. Can you point out where the following reasoning goes wrong?

def the_button_was_toggled(self, is_checked):
print("Checked?", is_checked)

The above defines a method of the the class MainWindow(QMainWindow).
A method is nothing more than a Python function embedded in a class, right?
So the two parameters of this function are self and is_checked. Parameters are usually used to pass values ‘into’ functions. The result of a function is normally obtained through the ‘return’ statement.

So, is_checked is used to pass information ‘into’ the method the_button_was_checked.

But how on earth is this possible? This is the first time this parameter appears in the script. Its value is still unknown!

I also considered that is_checked might be a Boolean attribute of the MainWindow class, or one of its parent classes. It might be used to access one of the internal values of the object. However, in that case I would expect the dot notation to be used. I couldn’t find any reference to is_checked on the Qt for Python web site.
Finally, as I pointed out in my first post, everything keeps working perfectly if I change is_checked to whatever other name I choose.

@Erik

So, is_checked is used to pass information ‘into’ the method the_button_was_checked.

Yes, howerver nothing prevents you for doing:

def the_button_was_toggled(self, is_checked):
    print("Checked")

Beside your IDE will complains is_checked is pass but never used, code will working! But parameter is_checked is crucial and required by Qt/Pyside, later explanation below

To make ever things even weirder, callback method can by just regular functions:

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        ...
        button.clicked.connect(the_button_was_toggled)
        ...

def the_button_was_toggled(is_checked):
    print("Checked?", is_checked)

And again, it will work!

But how on earth is this possible? This is the first time this parameter appears in the script. Its value is still unknown!

From static code analysis kind of yes, but during runtime value of is_checked is provided by Qt/Pyside internals, when click event is triggered Qt will run callback the_button_was_toggled it will check current state isChecked() of button and pass to callback method.
Similarity of spelling of is_checked variable/parameter and isChecked() method of QPushButton is just accidental (or better, it just describes what is going to happened).

I also considered that is_checked might be a Boolean attribute of the MainWindow class, or one of its parent classes. It might be used to access one of the internal values of the object. However, in that case I would expect the dot notation to be used.

If I understand your idea correctly it not necessary or not needed complication. Value is_checked and variable itself is kind of “temporary” or “relevant” only short time when event is triggered and callback executed.
Instead storing state of button as class attribute you can always just check with:

button = QPushButton("Press Me!")
button.setCheckable(True)
if button.isChecked():
    print("Checked")
else:
    print("Not checked")

I couldn’t find any reference to is_checked on the Qt for Python web site.

You will not find it, it is just name, as you noticed you can change name of parameter to anything like my_super_awesome_var, so why you expect to find this name inside documentation :wink: . Exactly same situation is, when you:

my_button = QPushButton("Press Me!")

you don’t expect to find my_button in documentation :wink:

Peace
Happy coding

Hi Michal,

Thank you very much, this makes it clear for me. :ok_hand:
I think the matter can be summarized as follows:

button.clicked.connect(function)

emits a signal clicked(), which is picked up by the function.
This function may be internal to a class (in which case it’s called a method) but it doesn’t need to.

The signal may either just trigger the function, or additionally supply it with a value, in our case the checked state, which can be either True or False. Weather or not this additional value is being sent to the receiving function depends on the Checkable state. The checked state is passed as an invisible actual parameter to the receiving function, where it takes the place of the formal parameter, in our case is_checked.

The clicked signal has either zero or one parameter(s).
Consequently, the second parameter (if there is any) of the slot function is always the checked state and never anything else.

According to the documentation QPushButton class inherits the following four signals from its parent class, QAbstractButton:

clicked()
pressed()
released()
toggled()

From these four signals, only clicked() and toggled() have the option to carry additional information, and that additional information is the checked state in both cases.

Again, thank you very much!

Yes, basically you are correct with description.

For methods you do not count self as parameter. This is telling Python that this function is bound to object (call it can be done only in object’s contest).

image