가장 큰 질문은 다음과 같습니다. 정확히 무엇을하려합니까? Qt 클래스는 어떤 이벤트를 받았습니까? 내가 아는 한, 당신은 어려운 일을하려고합니다. 그래서 왜 귀찮게합니까?
지연된 연결을 사용하여 슬롯을 호출 할 때마다 슬롯 호출을 나타내는 이벤트가 QMetaCallEvent
입니다. 이것은 슬롯에 연결된 신호 발사 또는 QMetaObject::invoke
또는 QMetaObject::invokeMethod
을 사용했기 때문일 수 있습니다. 대기중인 연결 비트가 중요한 부분입니다! 그들이 이벤트 큐 관리 오버 헤드가 있기 때문에 두 가지 조건 중 하나가 아래의 사실이 보유하지 않는 대기중인 연결이 , 동일한 스레드에서 개체 사이의 통화에 대해 기본적으로 사용하지됩니다
당신은 Qt::QueuedConnection
인수 QObject::connect
을에 제공 또는 QMetaObject::invoke[Method]
, 또는
thread()
통화가 발신되는 스레드와 다른 수신 객체의 - 통화시.
QMetaCallEvent
이벤트 클래스는 슬롯을 호출하는 데 필요한 정보를 전달합니다. 발신자 QObject
과 시그널 ID (호출이 신호 슬롯 연결에서 오는 경우), 대상 슬롯 식별자 및 슬롯으로 전달되어야하는 인수가 포함됩니다.
따라서 호출 된 슬롯이 가로 채기를 원하는 슬롯인지 여부와 전달 된 인수를 확인할 수 있습니다. 예를 들어, 단일 int
매개 변수가있는 슬롯을 호출하는 경우 *reinterpret_cast<int*>(metaCallEvent->args()[1])
은 해당 정수 값을 제공합니다. QMetaCallEvent
클래스 때문에 제로 번째의 인수가 반환 값에 사용됩니다 (있는 경우), 그래서 매개 변수가 면책 1.
베이스 색인, 당신은 응용 프로그램의 바이너리에 묶여 만들고있어 Qt의 구현 내부에 전체 Qt 버전 (전공.부 버전), 주요 버전에서 Qt가 제공하는 바이너리 호환성의 이점을 잃게됩니다. Qt의 다른 부 버전으로 전환 할 때 코드가 여전히 컴파일 될 수 있지만 제대로 작동하지 않습니다!
아래 내용은 Qt 5.2.0에 적용됩니다. 다른 버전은 보지 않았습니다!
따라서 QLabel::setNum
에 대한 호출을 가로 채기를 원한다고 가정하십시오. 다음과 같이 이러한 이벤트를 잡을 것 : 당신이보고 싶은 경우, 전 세계적으로는 metacall 시스템을 사용하여 호출하는 모든 슬롯은, 당신도 그렇게 할 수
#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);
...
}
감사합니다. 답변을 수락하기 위해, 나는 아직도 실제로 사용되는 예제와 QEvent 유형에서 사용할 수있는 것이 무엇인지 알고 싶습니다. – Rafe
연결된 신호가 나올 때마다'QMetaCallEvent'가 생성된다는 것은 거짓입니다. 신호 슬롯 메커니즘을 필요한 것보다 훨씬 느리게 만듭니다. –