Qt 元对象系统:使用带有名称的字符串发出信号
Qt metaobject system: emit signal using a string with its name
Qt signal/slot 系统很不错,但看起来它缺少一些真正有用的功能(或者至少我找不到如何使用它)。我有一个带有很多信号的 class,而这个 class 有一个 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 发出信号,我的代码将变得 much 更干净。
我查看了 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
,因为它看起来很隐蔽 headers?
我在我的程序中使用这个:
mCaller
是定义槽的对象,mSlotName
是槽的名称
QMetaObject::invokeMethod(mCaller, mSlotName.toLatin1().constData(), Qt::DirectConnection)
虽然QMetaObject::invokeMethod()
是更好的选择,但也可以只按数字发出信号:emit p->metaObject()->method(n).invoke(...);
Qt signal/slot 系统很不错,但看起来它缺少一些真正有用的功能(或者至少我找不到如何使用它)。我有一个带有很多信号的 class,而这个 class 有一个 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 发出信号,我的代码将变得 much 更干净。
我查看了 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
,因为它看起来很隐蔽 headers?
我在我的程序中使用这个:
mCaller
是定义槽的对象,mSlotName
是槽的名称
QMetaObject::invokeMethod(mCaller, mSlotName.toLatin1().constData(), Qt::DirectConnection)
虽然QMetaObject::invokeMethod()
是更好的选择,但也可以只按数字发出信号:emit p->metaObject()->method(n).invoke(...);