最大の質問は次のとおりです。あなたは正確に何をしようとしていますか?それらのイベントを受け取ったQtクラスは何ですか?私に関する限り、あなたは物事を一生懸命やろうとしているのに、なぜわざわざするのですか?
キューに入れられた接続がスロットを呼び出すために使用されるQMetaCallEvent
ときはいつでも、スロット呼び出しを表すイベントです。これは、スロットに接続された信号の発火、またはまたはの使用が原因である可能性があります。キューに入れられた接続ビットは重要な部分です!キューに入れられた接続は、以下の2つの条件のいずれかが当てはまらない限り、イベントキュー管理のオーバーヘッドがあるため、同じスレッド内のオブジェクト間の呼び出しにはデフォルトで使用されません。QMetaObject::invoke
QMetaObject::invokeMethod
または、、またはQt::QueuedConnection
に引数を指定しますQObject::connect
QMetaObject::invoke[Method]
受信オブジェクトthread()
は、呼び出しが発信されているスレッドとは異なります-呼び出し時。
イベントクラスはQMetaCallEvent
、スロットを呼び出すために必要な情報を伝達します。これには、送信者QObject
とその信号ID(呼び出しが信号スロット接続からのものである場合)、ターゲットスロット識別子、およびスロットに渡す必要のある引数が含まれます。
したがって、呼び出されたスロットがインターセプトしたいスロットであるかどうか、およびどの引数がスロットに渡されたかを確認できます。たとえば、単一のint
パラメータを使用してスロットを呼び出す場合*reinterpret_cast<int*>(metaCallEvent->args()[1])
、はその整数の値を提供します。戻り値がある場合は、0番目の引数が使用されるため、パラメーターには1を基数としてインデックスが付けられます。
免責事項クラスはQtの実装の内部にあるためQMetaCallEvent
、アプリケーションのバイナリを特定のQtバージョンに完全に関連付けて(major.minorバージョン全体)、メジャーバージョン全体でQtが提供するバイナリ互換性の利点を失います。コードはまだコンパイルされる可能性がありますが、Qtの別のマイナーバージョンに切り替えると正しく機能しなくなります。
以下はQt5.2.0に適用されますが、他のバージョンは調べていません。
したがって、への呼び出しを傍受したいとしますQLabel::setNum
。次のようなイベントをキャッチします。
#include <private/qobject_p.h> // Declaration of QMetaCallEvent
bool Object::eventFilter(QObject * watched, QEvent * event) {
QLabel * label = qobject_cast<QLabel*>(watched);
if (! label || event->type() != QEvent::MetaCall) return false;
QMetaCallEvent * mev = static_cast<QMetaCallEvent*>(event);
static int setNumIdx = QLabel::staticMetaObject.indexOfSlot("setNum(int)");
if (mev->id() != setNumIdx) return false;
int num = *reinterpret_cast<int*>(mev->args()[1]);
// At this point, we can invoke setNum ourselves and discard the event
label->setNum(num);
return true;
}
メタコールシステムを使用して呼び出されたすべてのスロットをグローバルに表示したい場合は、それも実行できます。基本クラスのテンプレートパラメータ化により、、、、、またはユーザー派生型など、任意QCoreApplication
のアプリケーションクラスを柔軟に使用できます。QGuiApplication
QApplication
template <class Base> class MetaCallWatcher : public Base {
MetaCallWatcher(int& argc, char** argv) : Base(argc, argv) {}
bool notify(QObject * receiver, QEvent * event) {
if (event->type() == QEvent::MetaCall) {
QMetaCallEvent * mev = static_cast<QMetaCallEvent*>(event);
QMetaMethod slot = receiver->metaObject()->method(mev->id());
qDebug() << "Metacall:" << receiver << slot.methodSignature();
}
return Base::notify(receiver, event);
}
}
int main(int argc, char ** argv) {
MetaCallWatcher<QApplication> app(argc, argv);
...
}