tags:

views:

198

answers:

1

In PyQt, there's a concept of signals and slots to connect objects to one another's functions, but I can't seem to find them referenced to functions not associated with other objects. For example, I want a dropdown list to have algorithm A or algorithm B run.

How does PyQt accomplish this functionality?

+2  A: 

Do you want the effect of changing the drop down list to call a function?

Connect the dropdown list's appropriate signal to your function.

For example with the QComboBox currentIndexChanged() signal. Connect that to a "wrapper" function that decides (based on the index) which function to call.

Edit: The wrapper can be very simple, like so:

functions = {0: reference_to_function_1, 1: reference_to_function_2}

def wrapper(index):
    functions[index]()

Edit2: If you want some alternate methods for connecting slots:

http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/pyqt4ref.html#connecting-signals-and-slots

Note when they are talking about Py or Qt signals, and when they are talking about Python functions or methods. E.g., these are the syntax for connecting a Qt signal to a Python function and a Python method:

QtCore.QObject.connect(a, QtCore.SIGNAL("QtSig()"), pyFunction) #function-style
QtCore.QObject.connect(a, QtCore.SIGNAL("QtSig()"), pyClass.pyMethod) #method-style
Chris Cameron
Right. This is kind of what I'm asking. Why do I need a wrapper function, though? That's what seems weird to me.
Mark
Because the signals are limited by the parameters they send. You need the function called to change depending on the parameter (i.e., which element in the drop down was clicked). Since QComboBox doesn't store function references (it stores QStrings with integer indices) it can't send a function reference as a parameter.
Chris Cameron
Very cool! Thanks a lot. So I can connect to this random class in a similar manner to this? button.connect(button, QtCore.SIGNAL("clicked()"),app, QtCore.SLOT("completelyUnrelatedFunction()")) Where that function is the slot?
Mark
I think so, but you're using a button now instead of a combo box?
Chris Cameron
Right. Just out of example. Probably should have used a combobox to ask how that parameters is passed though, haha
Mark
Personally I use this format: QtCore.QObject.connect(a, QtCore.SIGNAL("function1(type)"), b, QtCore.SLOT("function2(type)")), though apparently there's a nicer way in the newer pyqt versions.
Chris Cameron
is function1 always a predefined QT function? Such as "currentIndexChanged()" in this case?
Mark
It has to be a signal type, yes. QT defines signals on its widgets, not all functions are signals. If you need a signal that doesn't exist, you would have to create it.
Chris Cameron
Meanwhile function2 can be a function of my choice. Awesome, thank you so much for your help.
Mark
Sorry, maybe I'm oblivious, but this isn't working out for me. How can I define the behaviour in function2(type) without creating a brand new class? I can't seem to add just any class to the slots...
Mark
I just realized I gave you the format for when it has to be a Qt slot. See the link and examples I posted in the latest edit.
Chris Cameron
Amazing, thanks for the edit! Last question, promise, hahah. when you send the signal to a python function or method, how do they recieve the parameter from the signal (assuming you used for example currentIndexChanged which sends the int of the index it changed to)
Mark
In "general", the method/function signatures have to be the same. currentIndexChanged(int) specifies that an int is going to be passed as a parameter. So you have to provide a method/function that is compatible with that signature, e.g. def function2(index). Qt handles the parameter passing. There are many deviations from this though, I'd suggest playing around. I think there's even a way to send a parameterized signal to a function that doesn't accept arguments, or even one that accepts a variable number of arguments.
Chris Cameron