Painting Issue on QWidget outsite GUI thread

我怕爱的太早我们不能终老 提交于 2019-12-07 12:21:09

问题


I am developing an appliation in which I want to continuously receive images from remote host and display them on my screen. for this I am following the given strategy 1) I have a main QWidget object which contains the QImage on it (works fine) 2) Images received from remote host are painted on QImage object, this work is done in a worker thread using QPainter. (works fine) 3) but the problem is that the image is not updated on QWidget, unless I resize the widget, because the repaint event is called for QWidget... Now if i repaint the QWidget from the worker thread it gives error "QPixmap: It is not safe to use pixmaps outside the GUI thread".. and application crashes.

Any help regarding this?


回答1:


Emit a signal from the worker thread with a QueuedConnection
or post an update event (QPaintEvent) to the widget from the worker thread.

//--------------Send Queued signal---------------------
class WorkerThread : public QThread
{
    //...
signals:
    void updateImage();

protected:
    void run()
    {
        // construct QImage
        //...
        emit updateImage();
    }
    //...
};

//...
widgetThatPaintsImage->connect(
    workerThread, 
    SIGNAL(updateImage()), 
    SLOT(update()),
    Qt::QueuedConnection);
//...

//--------------postEvent Example-----------------------
class WorkerThread : public QThread
{
    //...
protected:
    void run()
    {
        //construct image
        if(widgetThatPaintsImage)
        {
            QCoreApplication::postEvent(
                widgetThatPaintsImage, 
                new QPaintEvent(widgetThatPaintsImage->rect()));
        }
        //... 
    }

private:
    QPointer<QWidget> widgetThatPaintsImage;
};

Don't forget to synchronize the access to the image.
As an alternative to the synchronization, you could also send the image to the gui thread, like in the Mandelbrot Example.




回答2:


GUI operations outside the main thread are not allowed in Qt. All GUI operations need to be done in the main thread, the thread where QApplication lives. Any GUI operation in another thread gives unpredictable results, i.e. crashes.




回答3:


There is a big problem with qt if you would like to develop plugins. If the host application is non-qt application (lots of programs...), and you want to add 2 or 3 GUI plugin, you are in a big trouble (as i am).

The problem is that, there must be just 1 QApplication in one process. (Usually takes place in main) If you write a plugin you cant afford to lock the host application with a QApplication.exec().

In this case you can create a QThread with QApplication and exec in the run() function. It will work properly. But this one cant solve the original problem. Your second plugin cant has a QApplication ... because the host process has one. (giving Qapplication pointer into a shared memory is not an option ... because QWidget must create on GUI thread ... there is always one...)

And for your question here is the answer. If you want to create just one plugin, you can use QMetaObject::invokeMethod this code set a pixmap to a label and updates gui.

QImage img;... bool succ = QMetaObject::invokeMethod(mainWin, "DisplaySlot", Qt::QueuedConnection, Q_ARG(QImage, img));

and add a public slot: to your displayer window

void mainWinClass::DisplaySlot(QImage qim) { (*(ui.label)).setPixmap(QPixmap::fromImage(qim)); (*(ui.label)).update(); }

I hope it helps.

If anyone know a solution to my problem ... described above (multiple gui plugin with qt in a host application) please write to me.



来源:https://stackoverflow.com/questions/1508151/painting-issue-on-qwidget-outsite-gui-thread

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!