如何将Qt信号/槽名存储到数据结构中
How to store Qt signal/slot names to a data structure?
我想将一个信号或插槽的名称存储到一个容器中,以便我可以检索它并与它建立连接。
一种方法是破解SIGNAL/SLOT宏并将信号/SLOT的名称存储为字符串,然后使用旧的连接语法创建如下连接void connect(QObject *dst, QString slot)
{
connect(this, SIGNAL(foo(void)), dst, slot.toLocal8Bit().data());
// void foo(void) is a member signal of "this" and is known
// at compile time
// but "dst" and "slot" are not known until runtime.
}
然而,这对我来说似乎有点太粗俗了。
我知道有另一种语法连接,也有一个对象类型的信号/插槽,这意味着一个不同的和(潜在的)不太黑客的解决方案。(注意,这不是Qt5中新的信号/槽语法)
但问题是,QMetaMethod
没有一个文档化的构造函数,它似乎不是可复制构造的。
还有一个问题,当信号/插槽的名称是动态的时,如何进行连接?
对于我的编码环境是Qt4和gcc 4.3.3与gnu++98
,所以需要Qt5和c++ 11的解决方案虽然受欢迎,但对我来说不太有用。
两个解决方案,我将寻找第三个。
用于示例的简单类:
#include <QObject>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass() : QObject() { }
void fireSignals()
{
qDebug() << "signal1 :" ;
emit signal1();
qDebug() << "signal2 :" ;
emit signal2();
qDebug() << "signal3 :" ;
emit signal3(3);
}
public slots:
void slot1() { qDebug() << "slot1"; }
void slot2() { qDebug() << "slot2"; }
void slot3() { qDebug() << "slot3"; }
void slot4(int i) { qDebug() << "slot4" << i; }
signals:
void signal1();
void signal2();
void signal3(int);
};
Qt4/c++ 98:
我没有Qt4,请告诉我这个解决方案是否有效。
已测试Qt 5.5, mingw 4.9.2, -std=c++98
它依赖于将信号或槽名转换为其索引,然后转换为相关的qmetamemethod。
注意:也可以存储QMetaMethod
对象。这种方法更安全,因为对插槽是否存在的检查更早发生,但是在创建QMap
之前需要有一个MyClass
实例,而存储插槽名称则更灵活。
// Get the index of a method, using obj's metaobject
QMetaMethod fetchIndexOfMethod(QObject* obj, const char* name)
{
const QMetaObject* meta_object = obj->metaObject();
QByteArray normalized_name = QMetaObject::normalizedSignature(name);
int index = meta_object->indexOfMethod(normalized_name.constData());
Q_ASSERT(index != -1);
return meta_object->method(index);
}
// A QObject::connect wrapper
QMetaObject::Connection dynamicConnection(QObject* source,
const char* signal_name,
QObject* dest,
const char* slot_name)
{
return QObject::connect(source, fetchIndexOfMethod(source, signal_name),
dest, fetchIndexOfMethod(dest, slot_name));
}
void first_way()
{
qDebug() << "nFirst way:";
QMap<QString, const char*> my_slots;
my_slots["id_slot1"] = "slot1()";
my_slots["id_slot2"] = "slot2()";
my_slots["id_slot3"] = "slot3()";
my_slots["id_slot4"] = "slot4(int)"; // slots with different signatures in the same container
MyClass object;
dynamicConnection(&object, "signal1()", &object, my_slots.value("id_slot1"));
dynamicConnection(&object, "signal1()", &object, my_slots.value("id_slot2"));
dynamicConnection(&object, "signal2()", &object, my_slots.value("id_slot3"));
dynamicConnection(&object, "signal3(int)", &object, my_slots.value("id_slot4"));
object.fireSignals();
}
Qt5/c++ 14:
已测试Qt 5.5, mingw 4.9.2, -std=c++14
使用指针指向成员函数。它是类型安全的,因此在同一个容器中不能有不同签名的槽。
template <typename T, typename R, typename ...Args>
struct PointerToMemberHelper
{
using type = R (T::*)(Args...);
};
void second_way()
{
qDebug() << "nSecond way:";
using MPTR_void = PointerToMemberHelper<MyClass, void>::type;
using MPTR_int = PointerToMemberHelper<MyClass, void, int>::type;
QMap<QString, MPTR_void> my_slots({{"id_slot1", MyClass::slot1},
{"id_slot2", MyClass::slot2},
{"id_slot3", MyClass::slot3}});
MyClass object;
QObject::connect(&object, MyClass::signal1, &object, my_slots.value("id_slot1"));
QObject::connect(&object, MyClass::signal1, &object, my_slots.value("id_slot2"));
QObject::connect(&object, MyClass::signal2, &object, my_slots.value("id_slot3"));
MPTR_int my_int_slot = MyClass::slot4; // or auto my_int_slot = ...
QObject::connect(&object, MyClass::signal3, &object, my_int_slot);
object.fireSignals();
}
目前正在尝试获得第三个解决方案的工作,基于lambdas和QMetaObject::invokeMethod
-但它不会比第二个解决方案做得更多。
相关文章:
- 用于存储由空格分隔的字符串的 C++/C 数据结构
- 哪些存储了不完整类型的 STL 数据结构可以用作类成员?
- 如何避免在数据结构中包含存储为字段的类?
- 如何读取文件并将该文件分类为不同类型的数据,这些数据都存储在结构中的特定数组中
- 用指向文件的指针存储数据结构
- 用于存储分组关系和支持外观的最佳数据结构
- unordered_set是否适合存储矢量<int>元素的数据结构?如果是这样,我将如何实现哈希函数?
- 如何将 JSON 键值(我使用 cpp boost 解析)存储在相关数据结构中?
- 用于存储网格(将具有负索引)的数据结构
- 是否可以检查存储在堆栈上的单词是否是回文,而C++中没有任何附加数据结构
- 从文件中读取数据并将其存储到结构中
- 存储数据列表并自动分配给结构的最佳方法是什么
- CRTP 模式 但是在数据结构中存储非同构类型
- 使用什么数据结构来存储基于游戏对象的二维单元地图?
- 存储大量会话的最有效数据结构是什么?
- 最佳数据结构存储文本文件中的数字集
- 可用于存储和管理整数集合的最佳C++数据结构是什么
- 用于存储数据的结构和外部二进制文件
- 存储数据结构
- 存储数据结构c++