Qt元对象系统:使用带有名称的字符串发出信号

时间:2015-02-27 10:43:58

标签: c++ qt qt-signals qmetaobject

Qt信号/插槽系统晃动,但看起来它缺少一些非常有用的功能(或者至少我找不到如何使用它)。我有一个包含大量信号的类,这个类有一个switch,需要根据变量的值发出正确的信号。现在我使用C预处理器解决这个问题:

#define CASE(_NAME) \    
case MyEnum_ ## _NAME: \
{ \
    emit MySignal_ ## _NAME(); \
    do_other_stuff(); \
    break; \
}

switch(val)
{
CASE(Val_1)
CASE(Val_2)
CASE(Val_3)
}

这看起来不对劲。我相信有更优雅的方式。 QMetaObject有一个indexOfSignal方法,可以使用带有名称的字符串为我提供信号的Qt内部ID。如果我可以使用此ID发出信号,我的代码将变得很多更清洁。

我已经看过moc生成的信号方法实现,看起来唯一不同的信号是一个数字:

void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, <signal_id>, _a);

其中<signal_id>是每个信号唯一的整数。

所以,问题是,我如何emit(int signalIdx)?或者至少有机会打电话给QMetaObject::activate,因为它看起来隐藏在私人标题中?

2 个答案:

答案 0 :(得分:4)

使用 QMetaObject::invokeMethod

我在我的程序中使用它:

mCaller是定义槽的对象,mSlotName是槽的名称

QMetaObject::invokeMethod(mCaller, mSlotName.toLatin1().constData(), Qt::DirectConnection)

答案 1 :(得分:1)

尽管QMetaObject::invokeMethod()是更好的选择,但它也可以仅通过数字发出信号:emit p->metaObject()->method(n).invoke(...);