<>这是一个非常简单的方法,在C++中,将是:</p>
<ol>
<li><p>有一组(object,signal index)对,您希望得到信号。</p></li>
<li><p>在等待开始之前复制集合。</p></li>
<li><p>在插槽中,从复制的列表中删除(sender(),senderSignalIndex())元素。如果列表是空的,你就知道你完成了。</p></li>
</ol>
<P>该解决方案的好处是可移植性:该方法在PysEnEm和<EEM> C++中都有效。在</p>
在C++中,^ {<CD1>}习惯地被封装在^ {< CD2>}或^ {CD3>}宏中的方法参数调用。这些宏在方法代码前面加上一个“0”、“1”或“2”,以指示它是可调用的方法、信号还是插槽。调用<code>registerSignal</code>时跳过此方法代码,因为它需要一个原始方法名。在</p>
<p>由于在<code>registerSignal</code>中调用的<code>indexOfMethod</code>需要一个规范化的签名,<code>connect</code>方法将其规范化。在</p>
<pre class="lang-cpp prettyprint-override"><code>class SignalMerge : public QObject {
Q_OBJECT
#if QT_VERSION>=QT_VERSION_CHECK(5,0,0)
typedef QMetaObject::Connection Connection;
#else
typedef bool Connection;
#endif
typedef QPair<QObject*, int> ObjectMethod;
QSet<ObjectMethod> m_signals, m_pendingSignals;
void registerSignal(QObject * obj, const char * method) {
int index = obj->metaObject()->indexOfMethod(method);
if (index < 0) return;
m_signals.insert(ObjectMethod(obj, index));
}
Q_SLOT void merge() {
if (m_pendingSignals.isEmpty()) m_pendingSignals = m_signals;
m_pendingSignals.remove(ObjectMethod(sender(), senderSignalIndex()));
if (m_pendingSignals.isEmpty()) emit merged();
}
public:
void clear() {
foreach (ObjectMethod om, m_signals) {
QMetaObject::disconnect(om.first, om.second, this, staticMetaObject.indexOfSlot("merge()"));
}
m_signals.clear();
m_pendingSignals.clear();
}
Q_SIGNAL void merged();
Connection connect(QObject *sender, const char *signal, Qt::ConnectionType type = Qt::AutoConnection) {
Connection conn = QObject::connect(sender, signal, this, SLOT(merge()), type);
if (conn) registerSignal(sender, QMetaObject::normalizedSignature(signal+1));
return conn;
}
};
</code></pre>