在QWidget外部GUI线程上绘画问题

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

有关于此的任何帮助?

使用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示例 。

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

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

问题是,一个进程中只能有一个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(); }

我希望它有帮助。

如果有人知道我的问题的解决方案…上面描述(多个GUI插件与主机应用程序中的QT),请写信给我。