[英]Qt5.15: how to access widget object from a QtConcurrent function
我希望从 QtConcurrent function 更新进度条小部件并遇到以下问题:
a) 如果我将此 function 声明为:
void myRunFunction(QString str)
然后我通过以下方式成功地将其编程为并发:
QFuture<void> t1 = QtConcurrent::run(myRunFunction, QString("A"));
但是我无法从 function 内部访问我的 GUI 的任何 Qt 小部件(“无法解析标识符'小部件'”)。
b) 如果我将此 function 声明为:
void mainForm::myRunFunction(QString str)
然后我成功地访问了其中的小部件,但不能再将其编程为并发获取编译器错误:
error: invalid use of non-static member function ‘void mainForm::myRunFunction(QString)’
在线:
QFuture<void> t1 = QtConcurrent::run(myRunFunction, QString("A"));
我该如何解决这个问题? 非常感谢,马可
在 Qt 中,所有小部件都应位于主 GUI 线程中。 所有其他线程不应该直接从主线程访问小部件,Qt 在这里不保证线程安全。 解决办法是什么? 使用 Qt 的内置队列机制。 有两种方法。
从文档:
(Qt::AutoConnection) 如果接收器位于发出信号的线程中,则使用 Qt::DirectConnection。 否则,使用 Qt::QueuedConnection。 连接类型在信号发出时确定。
如何为调用者提供指向被调用者的指针? 我建议使用闭包(带捕获的 lambda)。
但要小心你的对象的生命周期。 您现在有责任检查捕获的指向小部件的指针指向的有效小部件是否比非 GUI 线程的生命周期长。
根据您的代码,第二个变体更适合您。 有一个小例子:
// guiwidget.h
class GuiWidget : public QWidget
{
Q_OBJECT
public:
GuiWidget(QWidget *parent = nullptr);
~GuiWidget() {};
// public function for variant 2
void function(int data) {
// update widget
}
// slot for variant 1
public slots:
void function_slot(int data) {
// update widget
}
};
在 you.cpp 文件的某处:
GuiWidget *widget = new GuiWidget(this);
// declare a lambda
auto f = [widget] (QString str)
{
for (int i = 0; i < str.toInt(); ++i) {
// do some job
// ...
// job is done
// send progress data to mainwidget
QMetaObject::invokeMethod(widget, [widget, i] ()
{
widget->function(i);
}, Qt::QueuedConnection);
}
};
auto t1 = QtConcurrent::run(f, "100");
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.