4

我正在开发一个应用程序,我想在其中连续接收来自远程主机的图像并将它们显示在我的屏幕上。为此,我遵循给定的策略 1)我有一个包含 QImage 的主 QWidget 对象(工作正常) 2)从远程主机接收到的图像被绘制在 QImage 对象上,这项工作是在使用 QPainter 的工作线程中完成的。(工作正常)3)但问题是图像没有在 QWidget 上更新,除非我调整小部件的大小,因为为 QWidget 调用了重绘事件......现在如果我从工作线程重绘 QWidget,它会给出错误“ QPixmap:在 GUI 线程之外使用像素图是不安全的”.. 并且应用程序崩溃。

对此有任何帮助吗?

4

3 回答 3

10

使用 a 从工作线程发出信号QueuedConnection
或从工作线程向小部件发布更新事件 ( QPaintEvent)。

//--------------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;
};

不要忘记同步对图像的访问。
作为同步的替代方法,您还可以将图像发送到 gui 线程,就像在Mandelbrot 示例中一样。

于 2009-10-02T07:37:53.410 回答
2

如果你想开发插件,qt 有一个很大的问题。如果宿主应用程序是非 qt 应用程序(很多程序...),并且您想添加 2 或 3 个 GUI 插件,那么您就有大麻烦了(就像我一样)。

问题是,一个进程中必须只有 1 个 QApplication。(通常发生在 main 中)如果你写一个插件,你不能用 QApplication.exec() 来锁定宿主应用程序。

在这种情况下,您可以在 run() 函数中使用 QApplication 和 exec 创建一个 QThread。它会正常工作。但是这个不能解决原来的问题。您的第二个插件不能有 QApplication ...因为主机进程有一个。(将 Qapplication 指针指向共享内存不是一种选择......因为 QWidget 必须在 GUI 线程上创建......总是有一个......)

对于您的问题,这里就是答案。如果您只想创建一个插件,您可以使用 QMetaObject::invokeMethod 这段代码将像素图设置为标签并更新 gui。

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

并添加一个公共插槽:到您的显示窗口

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

我希望它有所帮助。

如果有人知道我的问题的解决方案...如上所述(主机应用程序中带有 qt 的多个 gui 插件),请写信给我。

于 2011-07-15T12:41:36.047 回答
1

Qt 中不允许主线程之外的 GUI 操作。所有的 GUI 操作都需要在主线程中完成,主线程是 QApplication 所在的线程。另一个线程中的任何 GUI 操作都会产生不可预知的结果,即崩溃。

于 2009-10-02T07:50:32.663 回答