Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ QWidget外部GUI线程上的绘制问题_C++_Linux_Qt_Qwidget_Qimage - Fatal编程技术网

C++ QWidget外部GUI线程上的绘制问题

C++ QWidget外部GUI线程上的绘制问题,c++,linux,qt,qwidget,qimage,C++,Linux,Qt,Qwidget,Qimage,我正在开发一个应用程序,在这个应用程序中,我希望不断地从远程主机接收图像,并将它们显示在我的屏幕上。为此,我遵循给定的策略 1) 我有一个主QWidget对象,其中包含QImage(工作正常) 2) 从远程主机接收的图像被绘制在QImage对象上,这项工作是在使用QPaint的工作线程中完成的。(工程罚款) 3) 但问题是图像不会在QWidget上更新,除非我调整小部件的大小,因为重新绘制事件是为QWidget调用的。。。现在,如果我从工作线程重新绘制QWidget,它会给出错误“QPixmap

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


有关于此的帮助吗?

使用队列连接从工作线程发出信号
或者从工作线程向小部件发布更新事件(
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;
};
/--------------发送排队信号---------------------
类WorkerThread:publicQThread
{
//...
信号:
void updateImage();
受保护的:
无效运行()
{
//构造QImage
//...
emit updateImage();
}
//...
};
//...
WidgetHatPaintsImage->connect(
workerThread,
信号(updateImage()),
插槽(更新()),
Qt::QueuedConnection);
//...
//--------------事件后示例-----------------------
类WorkerThread:publicQThread
{
//...
受保护的:
无效运行()
{
//构建形象
if(widgetThatPaintsImage)
{
QCoreApplication::postEvent(
Widgetthatsimage,
新的QPaintEvent(widgetThatPaintsImage->rect());
}
//... 
}
私人:
QPointer widgetThatPaintsImage;
};
不要忘记同步对映像的访问。

作为同步的替代方法,您还可以将图像发送到gui线程,如中所示

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();
}

我希望有帮助

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