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

Qt metaobject system: emit signal using a string with its name

本文关键字:字符串 信号 对象 系统 Qt      更新时间:2023-10-16

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);

其中CCD_ 5是对于每个信号唯一的整数。

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

使用QMetaObject::invokeMethod

我在我的程序中使用这个:

mCaller是具有已定义插槽的对象,mSlotName是插槽的名称

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

虽然QMetaObject::invokeMethod()是更好的选择,但也可以仅按编号发出信号:emit p->metaObject()->method(n).invoke(...);