Search code examples
pythonpyqt4signals-slots

how to pass arguments to a function using a predefined SIGNAL in PyQT


lets suppose you have 3 QRadioButtons instances inside a class

self.Option1 = QRadioButton()
self.Option2 = QRadioButton()
self.Option2 = QRadioButton()

(for brevity i didn't wrote the entire script) and you want to use them to execute a particular function when the user clicks it, so you do

self.connect(self.Option1,SIGNAL("clicked()"), self.myFunction)
self.connect(self.Option2,SIGNAL("clicked()"), self.myFunction)
self.connect(self.Option2,SIGNAL("clicked()"), self.myFunction)

How do i pass arguments to to myFunction so it knows wich of the QRadioButtons was clicked by the user? so i can do stuff like

def myFunction(choice):
   if choice == Option1:
       do something
   if choice == Option2:
       do something

Right now i have 3 functions, each for every connect like this

self.connect(self.Option1,SIGNAL("clicked()"), self.myFunction1)
self.connect(self.Option2,SIGNAL("clicked()"), self.myFunction2)
self.connect(self.Option2,SIGNAL("clicked()"), self.myFunction2)

And this approach works just fine, but you can see how quickly the code can grow because with every widget i add i'll have to write at least one new function or modify the existing ones, its going to be a maintainance nightmare(not to mention that it looks ugly and it prevents code reuse).

A quick visit to google got me this:

    self.label = QLabel(" ")

    self.connect(self, SIGNAL("didSomething"),
                 self.update_label)
    self.do_something()

def do_something(self):
    self.emit(SIGNAL("didSomething"), "important", "information")

def update_label(self, value1, value2):
    self.label.setText(value1 + " " + value2)

(again i didnt include the entire script but you can check it out here) What he did was creating a method to define a custom emitter that sends arguments when emitted and then activated it manually using

self.do_something()

So naturally, the connect function picks this emition and pass the arguments to the function update_label, partially achieving what i want to do. But he is doing it manually, is there a way to automatically "intercept" standard signals(for example the clicked() signal QRadioButtons emit) and add arguments to it, so they get passed to a function to work with them?

Thanks in advance


Solution

  • The Qt solution of this problem is QSignalMapper I think. But I had the same problem before, and I figured out using "partial" function is simplier. Use it like that:

    from functools import partial
    
    self.connect(self.Option1,SIGNAL("clicked()"), partial(self.myFunction, 1))
    self.connect(self.Option2,SIGNAL("clicked()"), partial(self.myFunction, 2))
    self.connect(self.Option3,SIGNAL("clicked()"), partial(self.myFunction, 3))
    

    For more info: http://docs.python.org/library/functools.html#functools.partial