PDA

View Full Version : Signal/slot or direct method call within a class



mike_the_tv
9th March 2010, 17:35
I am starting out with Qt and think I have grasped the basic concepts such as signals and slots for conveying events such as button clicks from the GUI controls to my main application class. However I am not sure if I am trying to invent usages of signals/slots where they are just not appropriate and where a direct method call would be more appropriate.

I have a fairly complex GUI with QComboBox, QTabWidget, etc controls. Some of these widgets contents depends on the state of other widgets. All of these widgets are children of my main window class.

If I want to handle say the switching of application context due to the QTabWidget changing then I use the signal/slot mechanism to connect the currentChanged() signal from the QTabWidget to the slot method in my main class that will handle the actions required on the tab contents changing. That situation is onviously a signal/slot usage.

However I have other widgets on the GUI whose state must change as a result of say the QTabWidget changing. These controls can also change by user interaction. For example, I have a QComboBox whose contents depends on the QTabWidget selection. The state of several other QCheckBox widgets however depends on the QComboBox widget. For this I set the activated() signal of the QComboBox to call a slot method in my main class that sets the state of the QCheckBox widgets appropriately. Again this to me is a signal/slot usage no question. The QComboBox widgets contents is again updated as a result of the currentChanged() signal from the QTabWidget. However as a result of setting the QComboBox I now need to change the QCheckBox widgets. The signal/slot parameters do not allow me to simply chain the slots from the original QTabWidget change onto both the QComboBox and then the QCheckBox widgets.

One way of handling this I thought of was to emit a signal from the QComboBox initiated slot member, which then is connected to the QCheckBox slot member to set their state. I also added a "shim" member between the standard QCheckBox widgets clicked() signals to re-emit the same signal I use from the QComboBox slot so that one slot function ends up doing the common work, with the "shim" slot function only there to get the signal parameters I need from both sources, Is this reasonable?

I have done the above in several places now within my main window class, effectively emitting signals internal to my class, connected to slots within the same class. Should I really be using signals/slots in this way or am I just inventing unnecessary usages of signals and slot where in fact a direct method call from one class member to another member member of the same class would be more appropriate.

I can sort of see advantages both ways. Speed possibly for direct method calls. However signals/slots maybe win if I genuinely have an event as a result of which I may want to execute one or more methods, but I don't want to have to explicitly list each method that needs to be called in the code (excluding the connections with connect()), especially if the signal can be emitted from more than one place.

Also is emitting the same signal from more than one place within a single class good practice?

Thanks for any advice/guidance anyone can offer.

pitonyak
9th March 2010, 20:00
There are a few nice things about slots and emitting a signal rather than a direct call.


Safe across thread boundaries.
The connected slot is dealt with in the event loop (more responsive).
Easy to add multiple handlers latter.

mike_the_tv
10th March 2010, 09:41
There are a few nice things about slots and emitting a signal rather than a direct call.


Safe across thread boundaries.

OK this is useful but not needed for my application.


The connected slot is dealt with in the event loop (more responsive).

I could be wrong, and would be happy to admit it as I am no expert on Qt, but I thought I read that unless you set the signal handling to be delayed or queued, can't remember the exact phrase, the slot was called directly via the signal. This seems to hold with what I have seen with the backtrace in the debugger. Queued signals I thought went via the event loop to provide some level of asynchonisity.


Easy to add multiple handlers latter.

Again this is true and one of the reasons for changing my code from single function calls to members to signals/slots. However if the point about slots being called directly from the signal is true and the fact that most slots I need to call from signals need fuller parameter lists than say the button clicked signal offers, I am finding myself writing signal wrappers that take some generic signal, find the context, then emit a more detailed signal. This more detailed signal is connected to one or more slots via connect() calls. I could simply make my signal wrapper call the explicit members directly. I have not lost any flexibility here in this case as all the members are in the same class and I have to add a connect() somewhere so why not an explicit call within the wrapper function.

This you see is where my quandtry exists. What are the best practices for signals/slots. Guidance if there are no hard and fast rules.
I had the same issues when I started writing C++ many years ago. I could just sit down and write code using C++ syntax or I could try and learn the concepts and ideas behind C++ so that I was not just writing C using C++ syntax.

pitonyak
10th March 2010, 15:33
I could be wrong, and would be happy to admit it as I am no expert on Qt, but I thought I read that unless you set the signal handling to be delayed or queued, can't remember the exact phrase, the slot was called directly via the signal. This seems to hold with what I have seen with the backtrace in the debugger. Queued signals I thought went via the event loop to provide some level of asynchonisity.
You can control the behavior
http://doc.trolltech.com/4.6/qt.html#ConnectionType-enum
http://doc.trolltech.com/4.6/signalsandslots.html

If things are small and simple, it will likely make no difference. You can be assured that there is overhead associated with the call (even ignoring the scaffolding that must be added to a class so that it can be used).

JD2000
11th March 2010, 14:53
I may be misunderstanding what is happening with the QComboBox but it is possible to to connect one signal to multiple slots, so re-emitting signals may not be necessary.

mike_the_tv
11th March 2010, 18:08
I may be misunderstanding what is happening with the QComboBox but it is possible to to connect one signal to multiple slots, so re-emitting signals may not be necessary.

A single signal to multiple slots is fine, but only if the signal parameters match those of the slots. Some of the slots are connected to other signals that provide more context parameters than a simple QComboBox can emit. Therefore I have one slot take the combobox signal, determine the state of other GUI controls to generate the context parameters, and then re-emit this.

What I really want to sort out is whether it is worth using signals/slots wholly within a class instance. I can see the benefits across class boundaries.

JD2000
11th March 2010, 18:49
I guess that you could implement a separate class/structure to hold all of your context parameters and pass a pointer to this with all of your signals.
That way you would have a common signature for all of your slots and possibly cleaner code.
I do not know how involved your GUI is so its difficult to advise on the best approach.