Multithreading QT-在不阻塞GUI的情况下显示小部件
我想显示一个小部件,用于在另一个函数(Multithreading QT-在不阻塞GUI的情况下显示小部件,multithreading,qt,user-interface,Multithreading,Qt,User Interface,我想显示一个小部件,用于在另一个函数(pthread)计算任务时显示动画加载gif 我尝试用QThread类对我的小部件进行子类化,并实现了方法run(),在这里我调用方法show()。然而,我的小部件GUI冻结了 如何启动一个单独处理GUI的小部件?除了主线程之外,任何东西都不能运行小部件 此外,除非您想更改Qt处理线程的方式,否则不应该从QThread继承 相反,创建一个从QObject继承的工作对象,并将其移动到新线程。你可以阅读 然后可以将worker对象移动到另一个线程,进行计算,并通
pthread
)计算任务时显示动画加载gif
我尝试用QThread
类对我的小部件进行子类化,并实现了方法run()
,在这里我调用方法show()
。然而,我的小部件GUI冻结了
如何启动一个单独处理GUI的小部件?除了主线程之外,任何东西都不能运行小部件 此外,除非您想更改Qt处理线程的方式,否则不应该从QThread继承 相反,创建一个从QObject继承的工作对象,并将其移动到新线程。你可以阅读 然后可以将worker对象移动到另一个线程,进行计算,并通过信号和插槽在主线程上与Gui小部件通信
// assuming you've added a run slot function to the Consumer class
connect(pThread, SIGNAL(started()), pObject, SLOT(run()));
connect(pObject, SIGNAL(finished()), pThread, SLOT(quit()));
connect(pObject, SIGNAL(finished()), pObject, SLOT(deleteLater()));
// Note the thread cleans itself up here, but if the app is quitting,
// waiting on the thread to finish may be required instead
connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()));
例如,下面是工人阶级的简要概述:-
class Worker : public QObject
{
Q_OBJECT
signals:
void finished();
void displayWidget();
private slots:
void run();
}
QThread pThread = new QThread;
Worker pObject = new Worker;
// move the pObject to the thread
pObject->moveToThread(pThread);
然后可以使用信号和插槽控制线程
// assuming you've added a run slot function to the Consumer class
connect(pThread, SIGNAL(started()), pObject, SLOT(run()));
connect(pObject, SIGNAL(finished()), pThread, SLOT(quit()));
connect(pObject, SIGNAL(finished()), pObject, SLOT(deleteLater()));
// Note the thread cleans itself up here, but if the app is quitting,
// waiting on the thread to finish may be required instead
connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()));
然后启动线程:-
pThread->start();
通过这种方式,它还可以将多个对象移动到单个新线程,而不是为每个对象实例创建一个新线程
例如,现在,如果您想在worker对象中的处理过程中的某个时间点显示一个小部件,您应该发出它的displayWidget()信号,之前将它连接到小部件的show()插槽
除了主线程,你不能在任何东西上运行小部件 此外,除非您想更改Qt处理线程的方式,否则不应该从QThread继承 相反,创建一个从QObject继承的工作对象,并将其移动到新线程。你可以阅读 然后可以将worker对象移动到另一个线程,进行计算,并通过信号和插槽在主线程上与Gui小部件通信
// assuming you've added a run slot function to the Consumer class
connect(pThread, SIGNAL(started()), pObject, SLOT(run()));
connect(pObject, SIGNAL(finished()), pThread, SLOT(quit()));
connect(pObject, SIGNAL(finished()), pObject, SLOT(deleteLater()));
// Note the thread cleans itself up here, but if the app is quitting,
// waiting on the thread to finish may be required instead
connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()));
例如,下面是工人阶级的简要概述:-
class Worker : public QObject
{
Q_OBJECT
signals:
void finished();
void displayWidget();
private slots:
void run();
}
QThread pThread = new QThread;
Worker pObject = new Worker;
// move the pObject to the thread
pObject->moveToThread(pThread);
然后可以使用信号和插槽控制线程
// assuming you've added a run slot function to the Consumer class
connect(pThread, SIGNAL(started()), pObject, SLOT(run()));
connect(pObject, SIGNAL(finished()), pThread, SLOT(quit()));
connect(pObject, SIGNAL(finished()), pObject, SLOT(deleteLater()));
// Note the thread cleans itself up here, but if the app is quitting,
// waiting on the thread to finish may be required instead
connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()));
然后启动线程:-
pThread->start();
通过这种方式,它还可以将多个对象移动到单个新线程,而不是为每个对象实例创建一个新线程
例如,现在,如果您想在worker对象中的处理过程中的某个时间点显示一个小部件,您应该发出它的displayWidget()信号,之前将它连接到小部件的show()插槽
不能直接从GUI线程以外的线程使用
QWidget
(或任何派生类)。您可以直接做的就是使用工作线程拥有的QImage
,并直接从该线程在其上绘制。在这里,直接意味着您只需调用对象的方法
您需要的是一种执行show()
的方法,它不是直接在调用线程中执行,而是在GUI线程的上下文中间接执行。这非常简单,因为QWidget::show()
是一个插槽。因此,在计算线程中,只需执行以下操作:
QMetaObject::invokeMethod(widget, "show");
就这些。invokeMethod
的实现将确定widget
位于不同的线程中,并将自动选择呼叫传递的QueuedConnection
方法。在内部,它将发布一个QMetaCallEvent
到小部件
。小部件的QObject::event
方法将对事件起作用,并调用show
方法。这将在GUI线程中发生
您可以使用相同的方法设置QProgressBar
,例如:
int value = ...;
QMetaObject::invokeMethod(progressBar, "setValue", Q_ARG(int, value));
不能直接从GUI线程以外的线程使用
QWidget
(或任何派生类)。您可以直接做的就是使用工作线程拥有的QImage
,并直接从该线程在其上绘制。在这里,直接意味着您只需调用对象的方法
您需要的是一种执行show()
的方法,它不是直接在调用线程中执行,而是在GUI线程的上下文中间接执行。这非常简单,因为QWidget::show()
是一个插槽。因此,在计算线程中,只需执行以下操作:
QMetaObject::invokeMethod(widget, "show");
就这些。invokeMethod
的实现将确定widget
位于不同的线程中,并将自动选择呼叫传递的QueuedConnection
方法。在内部,它将发布一个QMetaCallEvent
到小部件
。小部件的QObject::event
方法将对事件起作用,并调用show
方法。这将在GUI线程中发生
您可以使用相同的方法设置QProgressBar
,例如:
int value = ...;
QMetaObject::invokeMethod(progressBar, "setValue", Q_ARG(int, value));
你们没注意到user2543127用QThread子类化了他的小部件,这是他尝试的邪恶的根源吗?无法从UI线程(主线程)外部访问/创建UI。是的,这就是为什么我建议他创建一个从QObject继承的worker对象。但是您没有对此回答进行太多解释OP没有显示任何可使用的示例代码。我没有从一篇优秀的文章中重复信息,而是链接到它。所有信息都在那里。@Merlin069这些都不能解决提问者的问题:如何从非GUI线程调用
widget->show()
。“信号和插槽”的提及似乎朝着这个方向发展,但随后突然停止。关于如何正确使用QThread
的建议虽然有效,但在这里有些离题。教育学要求不要一次调用太多的新东西。你们没注意到user2543127用QThread子类化了他的小部件,这是他尝试的邪恶的根源吗?无法从UI线程(主线程)外部访问/创建UI。是的,这就是为什么我建议他创建一个从QObject继承的worker对象。但是您没有对此回答进行太多解释OP没有显示任何可使用的示例代码。我没有从一篇优秀的文章中重复信息,而是链接到它。所有的信息都在那里。@Merlin069这些都不能解决这个问题