Qt连接到插槽辅助接口
Qt connecting to slotted secondary interface
我的问题本质上是接口类中这个声明抽象信号的反面。 在该问题中,您持有指向槽 QObject 的指针,并尝试测试另一个对象的接口,该接口包含要连接到插槽对象的信号。
假设问题是相反的:你拿着一个指向发出信号的 QObject 的指针,你想测试一系列其他 QObject,看看它们是否实现了接收时隙。 如果是这样,您希望将它们全部连接到信号器。
我想使用的设计是,每个接收器都有一个主接口(QObject派生)和一个辅助插槽接口,我可以测试这些接口,即Q_DECLARE_INTERACE、qobject_cast等。
似乎辅助接口也必须是QObject派生的,否则您无法连接到它,但这打开了QObject的多重继承问题。
除了使用单个继承链之外,还有其他方法吗?
// receiver's primary interface
class IPrimary : public QObject
{
Q_OBJECT
public:
// etc.
};
// receiver's secondary interface with slot
class ISecondary : public QObject // QObject won't fly
{
Q_OBJECT // nope
public slots:
void OnReceiptOfSomething(...);
public:
// etc.
};
// signaler
class Signaler : public QObject
{
Q_OBJECT
signals:
void SignalOfSomething(...);
public:
// etc.
};
我不完全确定我是否理解您的目标,但似乎给定QObject *emitter
和信号名称signal_one
您希望在第二个QObject *receiver
中找到与signal_one
兼容的所有插槽并自动创建所需的连接。 如果是这样,那么我认为仅使用Qt
元数据基础设施是可能的 -QMetaObject
,QMetaMethod
等。
首先定义了一个函数are_compatible
,该函数比较两个QMetaMethod
实例的调用兼容性。
bool are_compatible (const QMetaMethod &signal_meta,
const QMetaMethod &slot_meta)
{
/*
* Work on the assumption that the arity of the signal must be at least that
* of the slot.
*/
if (signal_meta.parameterCount() < slot_meta.parameterCount())
return false;
/*
* Now check that all required parameters have the same type.
*/
for (int i = 0; i < slot_meta.parameterCount(); ++i) {
if (signal_meta.parameterType(i) != slot_meta.parameterType(i))
return false;
}
return true;
}
现在定义我们需要的主函数,该函数应自动将指定发射器中的命名信号连接到指定接收器中的所有兼容插槽。
void connect_where_possible (const char *signal_name,
QObject *emitter,
QObject *receiver)
{
const auto *emitter_meta_object = emitter->metaObject();
/*
* Look for signal_name in the emitter's metadata.
*/
auto index_of_signal = emitter_meta_object->indexOfSignal(signal_name);
if (index_of_signal == -1)
return;
/*
* Get the signal's associated QMetaMethod.
*/
const auto signal_meta_method = emitter_meta_object->method(index_of_signal);
/*
* Now go through the receiver's methods. We could naively attempt to
* connect to each and every slot knowing that the Qt runtime will only
* succeed when the signal and slot are compatible. A nicer/cleaner
* implementation is to use the metadata available to check for
* compatibility _before_ attempting to connect -- if only to avoid unwanted
* warning messages on the console.
*/
const auto *receiver_meta_object = receiver->metaObject();
for (int method_index = 0; method_index < receiver_meta_object->methodCount(); ++method_index) {
const auto receiver_slot_method = receiver_meta_object->method(method_index);
if (receiver_slot_method.methodType() == QMetaMethod::Slot) {
/*
* Found a slot so check it's compatibility and, if ok, try to connect.
*/
if (are_compatible(signal_meta_method, receiver_slot_method)) {
QObject::connect(emitter, signal_meta_method, receiver, receiver_slot_method);
}
}
}
}
通过一个例子,尝试以下代码...
class signaler: public QObject {
Q_OBJECT;
signals:
void sig1(int i, float f);
};
class receiver: public QObject {
Q_OBJECT;
public slots:
void slot1 (int i, float f) const
{
std::cerr << "nreceiver::slot1(i = " << i << ", f = " << f << ")";
}
void slot2 (int i) const
{
std::cerr << "nreceiver::slot2(i = " << i << ")";
}
void slot3 (float f) const
{
std::cerr << "nreceiver::slot3(f = " << f << ")";
}
};
...
signaler signaler;
receiver receiver;
connect_where_possible(QMetaObject::normalizedSignature("sig1(int, float)"), &signaler, &receiver);
signaler.sig1(10, 20.0f);
我看到输出...
receiver::slot1(i = 10, f = 20)
receiver::slot2(i = 10)
因此,正如预期的那样,receiver::slot1
和receiver::slot2
是连接的,但receiver::slot3
不是因为它被认为是不兼容的。
相关文章:
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何在没有信号的情况下从C++执行QML插槽
- 从Q_INVOKABLE功能或插槽中更改QQuick图像源
- 升压信号2将插槽传递到成员功能以断开连接
- 如何在qt中将信号和插槽与另一个对象连接 --解决了
- C++ 信号和插槽不工作:插槽不响应事件
- NS3 插槽混淆(需要帮助理解)
- QObject::连接无法将信号连接到*this*对象的插槽
- QT 插槽未在主线程上调用
- 通过插槽和信号在不同线程中的两个qt对象之间进行通信
- 控制带有信号/插槽的Qt QML滑动视图
- Qt 信号/插槽问题
- QT5 信号不会激活插槽内的功能
- Qt5:连接:如果插槽的参数少于信号,如何使用"连接"
- 需要实例化不同类/对象并在启动时确定的硬件插槽的设计模式
- Qt信号和插槽如果从QRunnable或其他线程调用,则不起作用
- 连接来自 C++98 接口的 Qt 插槽和信号,无需 Qt、STL 或 Boost
- Qt连接到插槽辅助接口
- 将QObject接口信号连接到lambda插槽
- 如何将抽象信号连接到接口构造函数中的插槽?