我有一个后台线程,线程调用一些更新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.
}
你知道发生了什么事或我做错了什么吗?或者,有人可以建议我另一种方法来处理我的新手问题吗?
提前致谢,
埃内斯托
答案 0 :(得分:10)
我自己没有使用invokeMethod()
,但为了做到这一点,我通常只使用信号和插槽。例如,您可以创建一个class B
成员的信号,该信号连接到class 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)
可能在之前返回调用slot函数使得无法准备好返回值。
只要您指向类型为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
的任何信息,但他们可以通过精心定义的精确频道进行通信。