开发者

Qt, widget refresh, and ui interactability

开发者 https://www.devze.com 2023-03-11 15:16 出处:网络
I\'m sparkling brand new to Qt, and am finding it very rewarding to learn. I\'m trying to merge some existing C++ code with a new Qt GUI. Basically, the idea is to have images that are extracted from

I'm sparkling brand new to Qt, and am finding it very rewarding to learn. I'm trying to merge some existing C++ code with a new Qt GUI. Basically, the idea is to have images that are extracted from an .avi file be processed in the backend and then displayed in a QLabel on-screen. I have managed to get the following bit of code to display the frames cor开发者_如何学Pythonrectly:

while (frame = cvQueryFrame(capture))
{
    // Some processing code...

    QImage qImageFrame((uchar*) frame->imageData, frame->width, frame->height, frame->widthStep, QImage::Format_RGB888);
    qImageFrame = qImageFrame.rgbSwapped();
    QPixmap qFrame;

    qFrame.convertFromImage(qImageFrame);
    label->setPixmap(qFrame);
    label->repaint();

    cvWaitKey(10);
}

Now, however, this obviously means that the UI stops being responsive to user input until all the frames from the movie are displayed. How is something like this done?

NB: I am performing the processing using the openCV library, which expects the images in a certain format. One thing which I think I cannot do, for example, is work with the .avi file directly in the Qt domain.


I disagree with Tamás's suggestion that his answer is the "simplest" solution.

The quickest, least-invasive solution to your problem is to add qApp->processEvents(); into your loop. I would drop it in after the label->repaint(); and see what happens.


You should really have a look at the Qt Phonon multimedia framework. Might not get you the level of control you have with OpenCV over the media files, but it's worth a good looking into.

For your original question: you have to do the processing in a different thread. This gets tricky because you can only call GUI functions from the UI thread, and you (I suppose) don't want to be copying the image data around too much.

For a good run-down (and pointers to the Qt docs), have a look at Qt signaling across threads, one is GUI thread?. Notice it'll take extra work if you want to pass QImages directly.


Sometimes the simplest solution is the best. Create a worker thread by subclassing QRunnable for decoding your frames and send signals back to the GUI to update the frame. When Qt signals emitted across threads, they are queued and dispatched correctly. Especially in the case of a single worker thread, you won't have headaches because of concurrency issues. Copying QImage is not a problem, because it utilizes implicit sharing. To write your own implicitly shared data classes, use QSharedDataPointer (as far as I know, Qt uses it internally as well).


Using a thread is not the only (or indeed, necessarily the preferred) way to do this.

Your UI is blocking because you're using a blocking sleep (cvWaitKey). If you use QTimer instead and connect its timeout signal to a slot which draws the next frame, then your UI should stay responsive.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号