Getting TypeError: () missing 1 required positional argument: 'checked'

Heads up! You've already completed this tutorial.

Gdaliy_Garmiza | 2020-11-16 12:18:04 UTC | #1

Hi, Martin!

I purchased your book a couple of months ago. It helps me a lot. I'm currently developing my own application, where I try to implement the 'Open recent files' functionality in the main menu. It's quite similar to your example here: https://www.pythonguis.com/tutorials/transmitting-extra-data-qt-signals/ with the difference that I connect the 'triggered' signals to the QActions (the list of files, generated in the loop). But neither my nor your code works for me.

Both

button.clicked.connect(lambda checked, a=a: self.button_clicked(a)) # [in your 'signals_extra_3.py' script]

and

new_act.triggered.connect(lambda checked, filename=file: self.OpenRecent(filename)) # [in my code]

Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PySide2 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!

More info Get the book

give out the TypeError: () missing 1 required positional argument: 'checked'. I use PySide2 and Python 3.8

Thanks.


martin | 2020-11-16 14:51:04 UTC | #2

Hi @Gdaliy_Garmiza welcome to the forum! Glad you're finding the book useful.

Yep, this unfortunately due to differences in how the .triggered() and .clicked() signals work between version of PyQt5 (& PySide2). The "checked" parameter is (according to the documentation) supposed to be sent with the .triggered signal, for example, but it isn't

Can you check if this also happens when connecting to a real method (vs. a lambda)? I wonder if that has something to do with it.

If you don't need the checked parameter (i.e. the action or button is not toggleable) you can just remove that parameter from your receiver method/function.


Gdaliy_Garmiza | 2020-11-17 00:53:23 UTC | #3

Hi, @martin!

Thanks for your quick response. I seem to have tried almost all the combinations with no success.

E.g.:

python
#  self.OpenRecentList — list of the full filenames/paths

for file in self.OpenRecentList:
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(lambda filename=file: self.OpenRecent(filename))

def OpenRecent(self, file):

# Code that opens a file

Result: When triggering the created actions(menu items) it tries to pass the boolean instead of the filename, because the error “File False not found” is raised within my app. It seems to be the boolean from the ‘checked’ parameter which is sent from the triggered signal, but omitted in my code.

python
for file in self.OpenRecentList:
    def open_recent_connector(filename=file):
        return self.OpenRecent(filename)
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(open_recent_connector)

Result: the same as above.

python
for file in self.OpenRecentList:
    def open_recent_connector(checked, filename=file):
        return self.OpenRecent(filename)
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(open_recent_connector)

Result (on triggering the action): TypeError: open_recent_connector() missing 1 required positional argument: 'checked'.

python
for file in self.OpenRecentList:
    filename = file
    def open_recent_connector():
        return self.OpenRecent(filename)
    new_act = QAction(file, self)
    self.menuOpen_Recent.addAction(new_act)
    new_act.triggered.connect(open_recent_connector)

Result (on triggering the action): the OpenRecent function is called (it opens the file), but the ‘loop problem’, described in your book, occurs. It passes the value of the last iteration when any QAction is triggered, and my app always opens the last file in the list.

Trying to fix it using your 'naming method' I went even as far as that:

python
new_act = []
for ind, file in enumerate(self.OpenRecentList):
    def open_recent_connector():
        filename = self.OpenRecentList[ind]
        return self.OpenRecent(filename)
    new_act.append(QAction(file, self))
    self.menuOpen_Recent.addAction(new_act[ind])
    new_act[ind].triggered.connect(open_recent_connector)

Result (on triggering the action): the same as above (the loop problem).


Gdaliy_Garmiza | 2020-11-17 17:41:40 UTC | #4

Hey, @martin

I have found the correct solution how to do this without lambda here: https://stackoverflow.com/questions/52283469/using-qsignalmapper

Here is the code which worked for me:

from functools import partial ...

python
def open_recent_menu_builder(self):
     for file in self.OpenRecentList:
          new_act = QAction(file, self)
          self.menuOpen_Recent.addAction(new_act)
          new_act.triggered.connect(partial(self.OpenRecent, file))

def OpenRecent(self, file):

# Code that opens a file

Jesus_Gangoso_Burgos | 2021-01-07 16:06:36 UTC | #5

Hi,

in order the code in the signals_extra_3.py script work, change "checked" by "*args". That is,

button.clicked.connect(lambda *args, val=a: self.button_clicked(val)) # <1>

in line 25.


Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!

More info Get the book

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Getting TypeError: () missing 1 required positional argument: 'checked' was written by Martin Fitzpatrick .

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt.