Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.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
从非主线程定向QtGUI_Qt_Qt5 - Fatal编程技术网

从非主线程定向QtGUI

从非主线程定向QtGUI,qt,qt5,Qt,Qt5,我知道以下不是正常的Qt模式,但我想从非主线程创建/指导主线程GUI元素 我们的目标是启动一个独立的线程,它可以运行很长一段时间并完成自己的事情。我不想在主窗口中为子线程可能做的每一件GUI事情设置挂钩。我希望子线程能够显示异步通知,例如,在后台使用进度条处理事情,等等 我创建一个worker对象并将其移动到辅助线程。当线程启动时,它向worker对象发出信号,为QProgressDialog实例化包装器,以模拟次线程“做自己的事情”。然后,此包装器被移回主线程,并发布一个事件,该事件导致包装器

我知道以下不是正常的Qt模式,但我想从非主线程创建/指导主线程GUI元素

我们的目标是启动一个独立的线程,它可以运行很长一段时间并完成自己的事情。我不想在主窗口中为子线程可能做的每一件GUI事情设置挂钩。我希望子线程能够显示异步通知,例如,在后台使用进度条处理事情,等等

我创建一个worker对象并将其移动到辅助线程。当线程启动时,它向worker对象发出信号,为
QProgressDialog
实例化包装器,以模拟次线程“做自己的事情”。然后,此包装器被移回主线程,并发布一个事件,该事件导致包装器实际创建
QProgressDialog
,这发生在主线程中。到现在为止,一直都还不错。然后,在次线程中的长时间运行循环中,我发出一个信号,期望它越过线程边界并更新
QProgressDialog
。信号似乎到达了与信号相连的主回路的lambda,但是 未到达已移动到主线程的对象。有趣的是,我可以发布一个事件来更新进度,因此我知道事件循环正在运行。我尝试了许多默认连接和排队连接的变体,在移动到新线程之前和之后连接,没有实际的gui组件(只是调试文本)、基于堆栈的对象与堆对象等。我的理解是,Qt自动确定接收对象是否与发送对象位于不同的线程中,如果是,发布事件循环拾取的事件。问题可能是在启动子线程后启动主线程(
QApplication::exec()

在下面的代码中,main.cpp中的debug msg正确地接收事件并打印消息,因此信号跨越了线程边界。它只是没有到达我的包装器对象。为什么不呢

谢谢

Main.cpp

#include "task.h"

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    TestClass worker("Tc1");
    QThread *thr = new QThread;

    QObject::connect(thr, &QThread::started, &worker, &TestClass::doWork);
    QObject::connect(&worker, qOverload<int,int>(&TestClass::progress), [](int x, int y){
        qDebug() << x << "out of" << y;});
    QObject::connect(&worker, &TestClass::done, []{qDebug() << "Done";});

    worker.moveToThread(thr);

    thr->start();
    a.exec();
    thr->wait();
    thr->quit();
    qDebug("Done");

}
#包括“task.h”
int main(int argc,char*argv[]){
质量保证申请a(argc、argv);
测试类工作者(“Tc1”);
QThread*thr=新的QThread;
连接(thr,&QThread::started,&worker,&TestClass::doWork);
QObject::connect(&worker,qOverload(&TestClass::progress),[](int x,int y){
qDebug()show();
返回true;
案例集_值:
mWidget->setValue(mWidget->value()+1);
返回true;
违约:
返回false;
}
}
公众时段:
//这些插槽似乎不能跨线程边界工作
void show(){mWidget->show();}
void setmax(intx){mWidget->setmax(x);}
void setMinimum(intx){mWidget->setMinimum(x);}
无效设置值(整数x){
qDebug()设置值(x);
}
void requestValue(){emit requestedValue(mWidget->value());}
信号:
无效请求值(int);
};
//这没用
Q_DECLARE_元类型(ProgressDialogWrapper)
类TestClass:公共QObject{
Q_对象
私人:
QString名称;
公众:
TestClass(){}
TestClass(QString n):名称(n){}
~TestClass()覆盖{
qDebug()线程());
bool-okc=QObject::connect(这个,qOverload(&TestClass::progress),
&pdw,&ProgressDialogWrapper::setValue,
Qt::QueuedConnection);

qDebug()考虑您的
ProgressDialogWrapper::event
实现

bool event (QEvent *e) override
{
    switch(e->type()) {
    case QEvent::User:
        create();
        mWidget->show();
        return true;
    case SET_VALUE:
        mWidget->setValue(mWidget->value() + 1);
        return true;
    default:
        return false;
    }
}
您只处理
CREATE
SET\u VALUE
情况:此
ProgressDialogWrapper
实例将有效地丢弃所有其他事件,包括排队连接使用的
QEvent::MetaCall
事件

将当前实现替换为

bool event (QEvent *e) override
{
    switch(e->type()) {
    case QEvent::User:
        create();
        mWidget->show();
        return true;
    case SET_VALUE:
        mWidget->setValue(mWidget->value() + 1);
        return true;
    default:

        /*
         * Defer to the base class implementation.
         */
        return return QObject::event(e);
    }
}

应该可以解决问题。

完全正常,谢谢!
bool event (QEvent *e) override
{
    switch(e->type()) {
    case QEvent::User:
        create();
        mWidget->show();
        return true;
    case SET_VALUE:
        mWidget->setValue(mWidget->value() + 1);
        return true;
    default:

        /*
         * Defer to the base class implementation.
         */
        return return QObject::event(e);
    }
}