2009-10-02 24 views
3

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

对此有何帮助?

回答

9

发射从工作线程的信号与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 Example

+0

你可以请给我一些代码片段,可以帮助。 – 2009-10-02 09:13:00

1

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

1

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

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

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

对于你的问题,这里是答案。如果你只想创建一个插件,你可以使用QMetaObject :: invokeMethod 这段代码将一个pixmap设置为标签并更新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插件),请写信给我。