PDA

View Full Version : How to run a widget's PaintEvent on another QThread



binary001
2nd April 2015, 17:19
Hi,

I change the pictures on my app background with Qtimer by using opacity (like Blend transaction).
It works well.



void MyDesktop:: paintEvent (QPaintEvent * ) {

QPainter BPainter1(this);
myBPix = QPixmap(fileName1);
BPainter1.setOpacity(1.0-_qBOpacity);
BPainter1.drawPixmap(1,1,this->width(),this->height(),myBPix);

QPainter Bpainter2(this);
myBPix2 = QPixmap(fileName2);
Bpainter2.setOpacity(_qBOpacity);
Bpainter2.drawPixmap(1,1,this->width(),this->height(),myBPix2);

}


Then I also move labels with Qtimer when I pressed a key.
Moving labels is ok but delay while background picture is changing.
So I want to run background picture changing on another Qthread.
To change picture opacity I use paintEvent on a widget.
How can I run a widget's paintEvent from another Qthread?
or Other Way?

Thanks.

yeye_olive
2nd April 2015, 17:50
All GUI operations must be run from the main thread, so you cannot do that. However, why do reload the pixmaps from disk every time you repaint the widget? This is likely the main reason for the bad performance you get. You should preload the pixmaps, e.g. in the widget's constructor, and see if that improves the situation.

binary001
2nd April 2015, 18:02
Thanks for your replay.

I want to use and reload so many pictures (just like wallpaper transaction) from disk. If all pictures are preloaded, app size is very big.
Now I try to use setGraphicsEffect from QThread.

stampede
2nd April 2015, 18:32
If all pictures are preloaded, app size is very big.
yeye_olive means that you should load them to memory when your app is running, not include them into app.exe.

Now I try to use setGraphicsEffect from QThread.
That probably won't work - all GUI related operations have to be used from the main thread, as already mentioned.

d_stranz
4th April 2015, 04:21
If all pictures are preloaded

You only need to have two pictures loaded at any time - the one you are fading in, and the one you are fading out. In your timeout handler, when the opacity reaches 0 (or 1, whatever), just emit a signal or call a method to load the next image (and swap the pixmaps so that the one that was faded in is now the one to fade out):



pixmap1 = pixmap2;
pixmap2.load( nextFileName );


It is not necessary to have two QPainter instances in the paint event. Just change the opacity on a single QPainter instance between drawing the two pixmaps.

The only thing you might want to preload is the list of picture file names. And you don't really even need to do that - you can create a QDirIterator as a member of your class, and simply call QDirIterator::next():



pixmap1 = pixmap2;
if ( myDirIterator.hasNext() == false )
myDirIterator = QDirIterator( path-to-picture-directory ); // restart from the beginning
pixmap2.load( myDirIterator.next() );


This code swaps the pixmaps, then checks to see if there are any files remaining in the list. If there are still files remaining, it loads the next one. If not, it resets the iterator back to the beginning and then loads the first one.