- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我的问题本质上是这个 Declare abstract signal in interface class 的反面.在那个问题中,您持有一个指向槽 QObject 的指针,并试图测试另一个对象的接口(interface),该接口(interface)包含您要连接到槽对象的信号。
假设问题是相反的:您持有一个指向发出信号的 QObject 的指针,并且您希望测试一系列其他 QObject 以查看它们是否实现了接收槽。如果是这样,您希望将它们全部连接到您的信号器。
我想使用的设计是每个接收器都有一个主要(QObject 派生的)接口(interface)和一个我可能测试的辅助槽接口(interface),即 Q_DECLARE_INTERACE、qobject_cast 等。
似乎次级接口(interface)也必须是 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
你想找到所有插槽在与 signal_one
兼容并自动创建所需连接的第二个 QObject *receiver
中。如果是这样,那么我认为仅使用 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
并非如此被视为不相容。
关于c++ - Qt连接到开槽二级接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54940418/
我是一名优秀的程序员,十分优秀!