4

イベントフィルターがあり、クリックして木の枝を展開/折りたたみすると気づきましたQEvent::MetaCall。これを使って自分の展開/折りたたみコードをロールすることを考えていましたが、アイテムのインデックスなどの情報を取得する方法がわかりません。

このMetaCallイベントタイプから利用できるものはありますか?

誰かが別のサイトでこれと同じ質問をしたことがわかりましたが、答えはありませんでした: http ://www.qtcentre.org/threads/37525-How-to-filter-QEvent-MetaCall

このイベントは通常何に使用されますか?

4

3 に答える 3

8

最大の質問は次のとおりです。あなたは正確に何をしようとしていますか?それらのイベントを受け取ったQtクラスは何ですか?私に関する限り、あなたは物事を一生懸命やろうとしているのに、なぜわざわざするのですか?

キューに入れられた接続がスロットを呼び出すために使用されるQMetaCallEventときはいつでも、スロット呼び出しを表すイベントです。これは、スロットに接続された信号の発火、またはまたはの使用が原因である可能性があります。キューに入れられた接続ビットは重要な部分です!キューに入れられた接続は、以下の2つの条件のいずれかが当てはまらない限り、イベントキュー管理のオーバーヘッドがあるため、同じスレッド内のオブジェクト間の呼び出しにはデフォルトで使用されません。QMetaObject::invokeQMetaObject::invokeMethod

  1. または、、またはQt::QueuedConnectionに引数を指定しますQObject::connectQMetaObject::invoke[Method]

  2. 受信オブジェクト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のアプリケーションクラスを柔軟に使用できます。QGuiApplicationQApplication

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);
  ...
}
于 2014-01-08T00:09:57.793 に答える
0

-typeイベントは、QEvent::MetaCall受信側のスロットに接続されている信号が発信されるたびに作成されQObjectます。カスタムフィルター/イベントハンドラーでこのイベントに反応すると、Qtの最も強力な機能であるシグナルスロットアーキテクチャを回避できるようです。どのスロットが呼び出されているか、そしてそのスロットが仮想であるかどうかを調べて、オーバーロードできるようにすることをお勧めします。

于 2012-06-12T08:26:29.033 に答える
-2

QEvent::MetaCallクロススレッド信号を配信するために使用されます。

于 2013-11-20T06:31:53.240 に答える