0

I am having a problem with the .itemClicked() method in PyQt4.

When I use it regularly Ex:

 listObj.itemClicked.connect(some_function)

I can use it in a function

def some_function(self,ITEM):

but I tried pass in another argument with the partial function from functools

listObj.itemClicked.connect( partial(some_function, extra_argument) )

and it replaces the ITEM with the extra_argument.

I also tried using the lambda function

listObj.itemClicked.connect(lambda: some_function(item, extra_argument))

this would work but it would return a tuple that would be stuck on my first item that I clicked.

Ex.

def some_function(self, ITEM, extra_argument):
    str(Item[0].text) # this would return a tuple with the second item 
                      # empty.

I checked around but all I could find was passing extra arguments on a button.

Thank you,

How to pass an extra arguments to PyQt slot?

Community
  • 1
  • 1
c.shoe
  • 13
  • 1
  • 5

2 Answers2

1

Short answer: You can't connect a two-argument slot to a one-argument signal. It just doesn't make any sense to do that. Qt won't be able to supply a value for the extra argument.

Of course you can write a Python function to receive the one-argument signal, attach a second argument to it, and call a second function. That's what you were trying to do when you attempted to use lambda, which passes a one-argument function to Qt but issues a two-argument function call within your program. This is how you do that:

listObj.itemClicked.connect(lambda item: some_function(item, extra_argument))

But check the link you supplied to see the pitfalls with this approach. Be sure you want a lambda expression and not a closure. This would be the closure approach:

def get_handler(self, extra):
    def h(item):
        some_function(item, extra)
    return h

listObj.itemClicked.connect(get_handler(extra_argument))

I find that I need to use closures occasionally with Qt callbacks.

Paul Cornelius
  • 9,245
  • 1
  • 15
  • 24
0

You should use it as follows:

extra_argument = {your value}
listObj.itemClicked.connect(lambda item, extra_argument= extra_argument: self.some_function(item, extra_argument))

def some_function(self, item, extra_argument):
    [...]

Or you can use partial but the default argument should be at the end:

listObj.itemClicked.connect(partial(self.some_function, extra_argument))

def some_function(self, extra_argument, item):
    [...]
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Thank you so Much! This solved the problem in the most elegant way possible. This finally solves all my problems. – c.shoe Apr 25 '17 at 16:47