我希望从QtConcurrent函数更新进度栏小部件,并解决了以下问题:
a)如果我将此函数声明为:
void myRunFunction(QString str)然后,我通过以下方式成功地将其编程为并发:
QFuture<void> t1 = QtConcurrent::run(myRunFunction, QString("A"));但是我不能从函数内部访问我的GUI的任何Qt部件(“无法解析标识符' widget‘")。
b)如果我将此函数声明为:
void mainForm::myRunFunction(QString str)然后,我成功地访问了它内部的小部件,但不能再将其编程为并发的,因为得到了编译器错误:
error: invalid use of non-static member function ‘void mainForm::myRunFunction(QString)’在第1行:
QFuture<void> t1 = QtConcurrent::run(myRunFunction, QString("A"));我该如何解决这个问题?非常感谢你,马可
发布于 2020-08-06 22:33:08
在Qt中,所有小部件都应该驻留在主GUI线程中。所有其他线程都不应该直接从主线程访问widgets,Qt在这里不保证线程安全。解决方案是什么?使用Qt的内置队列机制。有两种方法。
来自文档:
(Qt::AutoConnection)如果接收器位于发出信号的线程中,则使用Qt::DirectConnection。否则,将使用Qt::QueuedConnection。当发出信号时,确定连接类型。
如果您的第二个线程中没有任何QMetaObject::invokeMethod.,请使用
如何为调用者提供指向被调用者的指针?我推荐使用闭包(带有捕获的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
}
};在您的.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");https://stackoverflow.com/questions/63285615
复制相似问题