PDA

View Full Version : QWidget with "encapsulated thread"



phixx
3rd March 2008, 17:21
Hello,

I'm writing a viewer application that needs to render bitmaps in different ways. At the moment, I'm thinking of standard QImage/QPixmap operations and xvideo overlay.

I'd like to hide the differences in a QWidget-derived class. ( That is either having a base class defining the interface and two derived classes, or a single class with both standard and xvideo rendering functionality).

My problem is that I need some cpu time for format conversions, which I'd like to keep away from the gui thread. My image source provides frames in its own format, that need to be more or less converted, depending on the rendering mode.

Im basically thinking of a class with this interface:


class renderclass : public QWidget
{
void paintEvent ( QPaintEvent * /* event */ );
public slots:
void newImage( some_image_struct* pImg );
}

New images should be announced by a signal connected to "newImage". On signal reception, image data needs to be processed by a worker thread. When using the standard rendering method, results need to be copied to a QPixmap which is then painted by the next paintEvent call.

This is what I have in mind - but Im not sure about the details. My main problem is that I dont have little in-depth knowledge about signals, slots and threads.

My questions:
- Ive read that I can move QObjects from one thread to another, so that slot functions are executed in the new thread's context. Can I legally move QWidgets to another thread? ( The overwritten paintEvent function should still be executed by the GUI thread, as paintEvent is not a slot. correct?)

- My QWidget-derived class should maintain its own thread for image conversion. Inheriting from both QWidget and QThread will not work, AFAIK. Im thinking of a QThread member inside my widget. So Im planning to have a QWidget derived class, which is, in terms of thread affinity, owned by one of its own members ( instance of QThread). Are there any problems with this idea?

- A more simple solution would be to have a Widget owned by the GUI-tread with a QThread-based member owned by itself. This way the widget's slots would be executed by the GUI thread. Nevertheless, GUI thread utilization can be minimized, as incoming signals only need to be forwarded to the worker thread member object. (Which then uses its own thread...)
This way, I would get a cleaner design, but I need one more slot to be triggered. Do I have to expect notable performance loss here?

And my last question: Do I miss any concept that makes things more easy for me?

Thanks for reading!
phixx

jpn
3rd March 2008, 17:26
Have you seen the Mandelbrot Example (http://doc.trolltech.com/latest/threads-mandelbrot.html)?

THRESHE
3rd March 2008, 17:35
I would implement a thread that inherits QThread and call run on it when signal that is connected to ypur newImage slot recieved. Also I would implement a signal in your thread class that will tell your GUI that conversion is completed. And maybe it should send data to QWidget that will be rendered. I suppose you are thinking in the right direction but mixing GUI and logics isn't best idea if you ask me :)

phixx
3rd March 2008, 18:18
thanks for your answers.

@THRESHE: I perfectly understand your point about mixing GUI and logics, and I would not think about this, if there weren't the alternative way of rendering based on X video extensions. If I use Xv overlay, I do not need a GUI thread at all to paint a new image. I may also aquire YUV images so YUV->RGB conversions are needed, when Xv is not used. (And they can be omitted when it is)

I already have some kind of "image acquisition" thread that could be used for conversion, but I hate the idea of having these distinctions there. The acquisition thread would then require knowledge of the current rendering mode, and I would need to have "two interfaces" between display widget and acquisition thread...


I would implement a thread that inherits QThread and call run on it when signal that is connected to ypur newImage slot recieved.
This means I would start a new thread for each image to be displayed? what about the overhead? there may be up to 200 frames/sec...

THRESHE
3rd March 2008, 18:48
If I use Xv overlay, I do not need a GUI thread at all to paint a new image.
So why do you want to use QWidget if you don't need to?


This means I would start a new thread for each image to be displayed? what about the overhead? there may be up to 200 frames/sec...
You can schedule your images to prevent this.

phixx
3rd March 2008, 19:42
So why do you want to use QWidget if you don't need to?

- I'd like to have a QImage/QPixmap based rendering mode where the image is painted by the GUI thread. QWidget is used here, like intended. The process is straight forward: Image is aquired, converted to Qimage and sent to the widgets slot. Eventually, format conversions are done.
- I'd like to have an alternative rendering mode using xvideo (Linux). Video is displayed in a completely different manner. But (eventually) I still need to fill my window with a certain color key. This is easily done with a widget, just as the complete resize handling.
- For some reason it may happen that the image format is changed beyond the allowed image sizes for xvideo overlay (which vary from 1024x1024 to 2048x2048 as fas as I can tell). In these situations a fallback to standard display mode has to be done. Also, xv overlay should be enabled when the image size is changed again to something appropriate. This would be horribly complicated if there'd be a widget only in standard rendering mode....