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