PDA

View Full Version : Multiple Widgets of same class, one single thread for computation - adressing problem



burn2themax
5th July 2006, 12:10
I want to dynamically create 10 (or more) widgets of the same type (name it PlotWidget). These widgets are created within QMainWindow. Each of these widgets will show data of a different data-source.

One single thread is created (inside QMainWindow) for all the computations. Results are stored in this thread for each data-source.

Now the task is to send the data (maybe via signal/slot) to the mentioned widgets.
My problem is, that when connecting a signal (emitted from the thread) to the slot (inside the widgets), I can't name the target widget. This means, the thread has to iterate over all data-sources and send multiple signals to the widgets. But - how does the widget know, the data is for itself and not for a different widget.

Best way would be to have a mechanismn to register each widget with the thread, so the thread knows it's targets for the different data-sources. But how to accomplish this via signal/slots?
As far as I understand it, there has to be a dedicated signal for each widget to address it directly, but I would like to have it the dynamic way!

Any hints are greatly appreciated.

high_flyer
5th July 2006, 12:19
Best way would be to have a mechanismn to register each widget with the thread, so the thread knows it's targets for the different data-sources. But how to accomplish this via signal/slots?
I can't understand what the problem here is.
Could you give an example of what you mean?
As far as I see this, you probably have a Dialog class or similar that can see the thread object, and also the widgets that show the data, is it so?
If it is, where is the problem?

burn2themax
5th July 2006, 13:27
No, it's not a dialog.

The widgets and the thread are created in QMainWindow, so QMainWindow knows of both. The widgets are placed on docking windows or the like.
It is not a problem, to send data from the thread to the widgets via signal/slot. But this works like a broadcast. Each widget gets the same data.

The problem is, that each widget has to show different data, so I have to send it from the thread to the appropriate widget. To accomplish that, some kind of addressing is necessary. But signal/slot doesn't allow this - as far as I understand.

So the idea was, to register each widget with the thread, looping over the connected data-sources and sending data to the responsible widget for plotting. But using a list of pointers to the widgets doesn't work (the widgets are not updated then) and is bad design anyway.

The question is, what is the correct way to implement such a dynamic widget/thread relationship? I don't like to have a pool of signals (like dataReady1, dataReady2, ...) hardcoded in the app and then assigned to a dedicated widget. This is not dynamic, since the max number of signals is given at compile-time. The other possibility to emit the signal "dataReady" to all widgets and let the widget decide, whether the data is for itself isn't a better way either (signalling overhead).

jacek
5th July 2006, 13:42
But signal/slot doesn't allow this - as far as I understand.
Can't you add another parameter to that signal? For example an identifier, so the widgets can check whether they should discard data?

Other solution is to use custom events. This way you can send an event to a particular widget (all you need is a pointer to it).

eriwik
5th July 2006, 13:52
The question is, what is the correct way to implement such a dynamic widget/thread relationship? I don't like to have a pool of signals (like dataReady1, dataReady2, ...) hardcoded in the app and then assigned to a dedicated widget. This is not dynamic, since the max number of signals is given at compile-time. The other possibility to emit the signal "dataReady" to all widgets and let the widget decide, whether the data is for itself isn't a better way either (signalling overhead).

There are only two possible ways to do this, one is that the thread has a reference (pointer or whatever) to each data-widget and makes a call (function call, signal emit or whatever) to the correct widget. Or the thread will have to broadcast and it's up to each widget to see if the data is relevant or not. Both approaches have their advantages, the second for example allows for adding new widgets which displays some custom set of results without having to modify the thread.

You say you are affraid of signaling overhead, which I take as a sign that this is performance critical (since signaling overhead is quite low), then perhaps you should implement some king of asynchronic messaging, the thread sends out messages which are placed in a buffer which is read by the widgets.

Another approach (with no broadcasting) would be to use a collection of function-pointers. One pointer to each widget, the thread could then store them in some kind of associative container (a map) and based on the kind of information find the right pointer in the collection and perform the call.

burn2themax
5th July 2006, 14:32
@jacek
The idea with the identifier was one possible solution I came up with. But then I have to send a bunch of signals. Having e.g. 20 widgets and 20 data-sources I have to send 400 signals, that is not efficient.

Is there any sample for custom events? I'm using QT4.

@eriwik

There are only two possible ways to do this, one is that the thread has a reference (pointer or whatever) to each data-widget and makes a call (function call, signal emit or whatever) to the correct widget.


A function call is possible, if I use pointers to the widgets. But how to emit a signal to a specific widget?
Another problem comes into view then, function calls are not possible from one thread to another. I tried it and the screen doesn't update (obiously the GUI thread is not informed about the data added from a different thread). Explicitly calling "update" within the GUI thread doesn't help either.
It works with signal/slot, but then the addressing problem isn't solved.

elcuco
5th July 2006, 15:22
I found myself in that position a few months ago. Something like "QObject *sender" to be passed on the slots would save this problem...

As far as I know, Qt does not have such things.

jacek
5th July 2006, 16:11
Having e.g. 20 widgets and 20 data-sources I have to send 400 signals, that is not efficient.
Then maybe you need a DataSource object that will emit appropriate signal?

Another alternative is to use dynamic signals, but it's a bit hackish.
http://doc.trolltech.com/qq/qq16-dynamicqobject.html


Is there any sample for custom events? I'm using QT4.
All you need it to is subclass QEvent and reimplement QObject::customEvent() in receiver. To dispatch events you can use QCoreApplication::postEvent().


In Qt 4, custom events are created by subclassing QEvent and reimplementing the type() function to return a value in the range allocated for user events. Event-specific data can be stored in a way that is appropriate for your application. Custom events are still delivered to each object's customEvent() handler function, but as QEvent objects rather than as deprecated QCustomEvent objects.

Chicken Blood Machine
6th July 2006, 17:51
I found myself in that position a few months ago. Something like "QObject *sender" to be passed on the slots would save this problem...

As far as I know, Qt does not have such things.

It does. It's called QObject::sender(). Unfortunately, it would not help here as the OP's sender is always the same object.

@burn2themax - Have you considered using a signal multiplexor?

http://doc.trolltech.com/qq/qq08-action-multiplexer.html

You can use this to exclusively choose the widget you are intrested into to receive your signals. no other widgets will be notified.

jacek
6th July 2006, 18:56
Something like "QObject *sender" to be passed on the slots would save this problem...

As far as I know, Qt does not have such things.
But of course it has: QObject::sender()

elcuco
6th July 2006, 20:50
what do you say... you learn something new each day.

burn2themax
7th July 2006, 13:09
@jacek
I did a sample implementation with QEvent and... it works!! Thanks for this solution!

@Chicken Blood Machine
Thanks for the idea with the multiplexer! Seems to be an interesting concept for having multiple docs.
But in my situation the receiver-widget changes permanently, so I had to call "setCurrentObject" on and on. This produces too much overhead.