我有一个后台线程,该线程会调用一些更新 UI 的方法(以便显示进度条并在文本区域显示其他信息)。
如果我修改某些 UI 小部件值,则会引发“无法将事件发送到不同线程拥有的对象”断言错误。
在论坛上,我读到我可以使用 QMetaObject::invokeMethod 方法,但如果我将 Qt::DirectConnection 标志传递给它,它就会起作用,这实际上引发了上面显示的相同错误。
如果我使用 Qt::QueuedConnection 或 Qt::AutoConnection,invokeMethod 返回 false。
我的代码看起来类似于:
.h:
class A : public QMainWindow
{
Q_OBJECT
QProgressBar* pb;
public slots:
bool m(bool, int);
};
class B
{
A* a;
public:
void handleEvent();
};
.cpp:
bool A::m(bool x, int y)
{
pb->setValue(y);
return x;
}
void B::handleEvent()
{
//a->m(true, 12); //raises an assertion error
bool r;
//bool ret = QMetaObject::invokeMethod(a, "m", Qt::DirectConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //raises the same assertion error error
bool ret = QMetaObject::invokeMethod(a, "m", Qt::AutoConnection, Q_RETURN_ARG(bool, r), Q_ARG(bool, true), Q_ARG(int, 12)); //is ignored and ret contains false.
}
你知道发生了什么或者我做错了什么吗?或者,有人可以建议我另一种方法来处理我的新手问题吗?
提前致谢
埃内斯托
最佳答案
我自己没有使用过invokeMethod()
,但为此,我通常只使用信号和槽。例如,您可以创建一个信号作为 B 类
的成员,该信号连接到 A 类
中的插槽以更新进度:
class B : public QObject
{
Q_OBJECT
A* a;
signals:
void update_signal(bool, int);
public:
void handleEvent();
};
B::B()
{
//assuming a already points to the correct place...
connect(this, SIGNAL(update_signal(bool,int),
a, SLOT(m(bool,int)), Qt::QueuedConnection);
}
void B::handleEvent()
{
emit update_signal(true, 12);
}
A::m()
在这种情况下必须返回 void 但这不是问题,因为使用排队连接时,您无法获得返回值,因为调用是异步的 ( emit update_signal(true,12)
可能会在调用槽函数之前返回,从而无法准备好返回值。
只要您有指向类型A
的对象和类型B
的对象的指针,您实际上可以在任何地方执行此连接。这使得信号和槽非常灵活,因为您可以将 A
与 B
完全分离,但仍允许它们通过信号和槽进行通信。例如:
class B : public QObject
{
Q_OBJECT
signals:
void update_signal(bool, int);
public:
void handleEvent();
};
void B::handleEvent()
{
emit update_signal(true, 12);
}
class A : public QMainWindow
{
Q_OBJECT
QProgressBar* pb;
public slots:
void m(bool, int);
};
void A::m(bool x, int y)
{
pb->setValue(y);
}
int main()
{
A* a = new A();
B* b = new B();
QObject::connect(b, SIGNAL(update_signal(bool, int)),
a, SLOT(m(bool, int)), Qt::QueuedConnection);
//...
}
在这种情况下,b
不必存储指针或知道有关 a
的任何信息,但它们可以通过定义明确的薄 channel 进行通信。
关于c++ - Qt : Background thread refreshing UI thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2376835/