Das Ereignissystem
In Qt sind Ereignisse Objekte, die von der abstrakten Klasse „ QEvent “ abgeleitet sind und Vorgänge darstellen, die entweder innerhalb einer Anwendung oder als Folge externer Aktivitäten stattgefunden haben und von denen die Anwendung Kenntnis haben muss. Ereignisse können von jeder Instanz einer Unterklasse von ` QObject ` empfangen und verarbeitet werden, sind jedoch insbesondere für Widgets von Bedeutung. Dieses Dokument beschreibt, wie Ereignisse in einer typischen Anwendung übermittelt und verarbeitet werden.
Wie Ereignisse übermittelt werden
Wenn ein Ereignis eintritt, erstellt Qt ein Ereignisobjekt, um es darzustellen, indem es eine Instanz der entsprechenden Unterklasse von ` QEvent ` konstruiert, und übergibt es an eine bestimmte Instanz von ` QObject ` (oder eine ihrer Unterklassen), indem es deren Funktion ` event()` aufruft.
Diese Funktion verarbeitet das Ereignis nicht selbst; je nach Art des übermittelten Ereignisses ruft sie einen Ereignis-Handler für diesen spezifischen Ereignistyp auf und sendet eine Antwort zurück, je nachdem, ob das Ereignis akzeptiert oder ignoriert wurde.
Einige Ereignisse, wie z. B. „ QMouseEvent “ und „ QKeyEvent “, stammen vom Fenstersystem; andere, wie z. B. „ QTimerEvent “, stammen aus anderen Quellen; wieder andere stammen aus der Anwendung selbst.
Ereignistypen
Für die meisten Ereignistypen gibt es spezielle Klassen, insbesondere „ QResizeEvent “, „ QPaintEvent “, „ QMouseEvent “, „ QKeyEvent “ und „ QCloseEvent “. Jede Klasse ist eine Unterklasse von „ QEvent “ und fügt ereignisspezifische Funktionen hinzu. Beispielsweise fügt „ QResizeEvent “ die Methoden „ size()“ und „ oldSize()“ hinzu, damit Widgets erkennen können, wie sich ihre Abmessungen geändert haben.
Einige Klassen unterstützen mehr als einen tatsächlichen Ereignistyp. QMouseEvent unterstützt Mausklicks, Doppelklicks, Bewegungen und andere damit verbundene Operationen.
Jedem Ereignis ist ein Typ zugeordnet, der in ` QEvent::Type` definiert ist; dieser kann als praktische Quelle für Typinformationen zur Laufzeit genutzt werden, um schnell zu ermitteln, aus welcher Unterklasse ein bestimmtes Ereignisobjekt erstellt wurde.
Da Programme auf vielfältige und komplexe Weise reagieren müssen, sind die Mechanismen zur Ereignisübermittlung in Qt flexibel. Die Dokumentation zu ` QCoreApplication::notify()` fasst das Ganze prägnant zusammen; der Artikel „Another Look at Events“ im Qt Quarterly behandelt das Thema weniger prägnant. Hier werden wir genug erklären, um 95 % der Anwendungen abzudecken.
Ereignisbehandler
Die übliche Art der Ereignisübermittlung erfolgt durch den Aufruf einer virtuellen Funktion. Beispielsweise wird das Ereignis „ QPaintEvent “ durch den Aufruf von ` QWidget::paintEvent()` übermittelt. Diese virtuelle Funktion ist dafür zuständig, angemessen zu reagieren, in der Regel durch das Neuzeichnen des Widgets. Wenn Sie in Ihrer Implementierung der virtuellen Funktion nicht alle erforderlichen Schritte ausführen, müssen Sie möglicherweise die Implementierung der Basisklasse aufrufen.
Der folgende Code verarbeitet beispielsweise Klicks mit der linken Maustaste auf ein benutzerdefiniertes Checkbox-Widget, während alle anderen Klicks an die Basisklasse ` QCheckBox ` weitergeleitet werden:
void MyCheckBox::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
// handle left mouse button here
} else {
// pass on other buttons to base class
QCheckBox::mousePressEvent(event);
}
}Wenn Sie die Funktion der Basisklasse ersetzen möchten, müssen Sie alles selbst implementieren. Wenn Sie jedoch lediglich die Funktionalität der Basisklasse erweitern möchten, implementieren Sie die gewünschten Funktionen und rufen die Basisklasse auf, um das Standardverhalten für alle Fälle zu erhalten, die Sie nicht selbst behandeln möchten.
Gelegentlich gibt es keine solche ereignisspezifische Funktion, oder die ereignisspezifische Funktion reicht nicht aus. Das häufigste Beispiel betrifft das Drücken der Tabulatortaste. Normalerweise fängt ` QWidget ` diese ein, um den Tastaturfokus zu verschieben, aber einige Widgets benötigen die Tabulatortaste für ihre eigenen Zwecke.
Diese Objekte können ` QObject::event()` – den allgemeinen Ereignisbehandler – neu implementieren und ihre Ereignisbehandlung entweder vor oder nach der üblichen Behandlung durchführen oder die Funktion vollständig ersetzen. Ein sehr ungewöhnliches Widget, das sowohl die Tabulatortaste interpretiert als auch über ein anwendungsspezifisches benutzerdefiniertes Ereignis verfügt, könnte die folgende Funktion ` event()` enthalten:
bool MyWidget::event(QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() == Qt::Key_Tab) {
// special tab handling here
return true;
}
} else if (event->type() == MyCustomEventType) {
MyCustomEvent *myEvent = static_cast<MyCustomEvent *>(event);
// custom event handling here
return true;
}
return QWidget::event(event);
}Beachten Sie, dass ` QWidget::event()` weiterhin für alle nicht behandelten Fälle aufgerufen wird und dass der Rückgabewert angibt, ob ein Ereignis bearbeitet wurde; ein Wert von ` true ` verhindert, dass das Ereignis an andere Objekte weitergeleitet wird.
Ereignisfilter
Manchmal muss ein Objekt die Ereignisse, die an ein anderes Objekt übermittelt werden, überprüfen und möglicherweise abfangen. Beispielsweise möchten Dialogfelder häufig Tastendrücke für bestimmte Widgets filtern, um beispielsweise die Behandlung der Return-Taste anzupassen.
Die Funktion ` QObject::installEventFilter()` ermöglicht dies durch die Einrichtung eines Ereignisfilters, wodurch ein benanntes Filterobjekt die Ereignisse für ein Zielobjekt in seiner Funktion ` QObject::eventFilter()` empfängt. Ein Ereignisfilter verarbeitet Ereignisse vor dem Zielobjekt und kann die Ereignisse so nach Bedarf prüfen und verwerfen. Ein bestehender Ereignisfilter kann mit der Funktion ` QObject::removeEventFilter()` entfernt werden.
Wenn die Implementierung von ` eventFilter()` des Filterobjekts aufgerufen wird, kann es das Ereignis annehmen oder ablehnen und die weitere Verarbeitung des Ereignisses zulassen oder verweigern. Wenn alle Ereignisfilter die weitere Verarbeitung eines Ereignisses zulassen (indem sie jeweils „ false “ zurückgeben), wird das Ereignis an das Zielobjekt selbst gesendet. Wenn einer von ihnen die Verarbeitung abbricht (indem er „ true “ zurückgibt), erhalten das Zielobjekt und alle nachfolgenden Ereignisfilter das Ereignis überhaupt nicht zu sehen.
bool FilterObject::eventFilter(QObject *object, QEvent *event)
{
if (object == target && event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->key() == Qt::Key_Tab) {
// Special tab handling
return true;
} else
return false;
}
return false;
}Der obige Code zeigt eine weitere Möglichkeit, Tabulatortasten-Ereignisse abzufangen, die an ein bestimmtes Ziel-Widget gesendet werden. In diesem Fall verarbeitet der Filter die relevanten Ereignisse und gibt „ true “ zurück, um deren weitere Verarbeitung zu unterbinden. Alle anderen Ereignisse werden ignoriert, und der Filter gibt „ false “ zurück, damit diese über alle anderen auf dem Ziel-Widget installierten Ereignisfilter an das Ziel-Widget weitergeleitet werden können.
Es ist auch möglich, alle Ereignisse der gesamten Anwendung zu filtern, indem ein Ereignisfilter am Objekt „ QApplication “ oder „ QCoreApplication “ installiert wird. Solche globalen Ereignisfilter werden vor den objektspezifischen Filtern aufgerufen. Dies ist sehr leistungsstark, verlangsamt jedoch auch die Ereignisübermittlung jedes einzelnen Ereignisses in der gesamten Anwendung; stattdessen sollten im Allgemeinen die anderen besprochenen Techniken verwendet werden.
Ereignisse senden
Viele Anwendungen möchten eigene Ereignisse erstellen und senden. Sie können Ereignisse auf genau dieselbe Weise wie in der Qt-eigenen Ereignisschleife senden, indem Sie geeignete Ereignisobjekte erstellen und diese mit ` QCoreApplication::sendEvent()` und ` QCoreApplication::postEvent()` senden.
sendEvent() verarbeitet das Ereignis sofort. Bei der Rückkehr haben die Ereignisfilter und/oder das Objekt selbst das Ereignis bereits verarbeitet. Für viele Ereignisklassen gibt es eine Funktion namens ` isAccepted()`, die angibt, ob das Ereignis vom zuletzt aufgerufenen Handler akzeptiert oder abgelehnt wurde.
postEvent() stellt das Ereignis zur späteren Weiterleitung in eine Warteschlange. Beim nächsten Durchlauf der Haupt-Ereignisschleife von Qt werden alle gestellten Ereignisse mit einigen Optimierungen weitergeleitet. Liegen beispielsweise mehrere Größenänderungsereignisse vor, werden diese zu einem einzigen zusammengefasst. Das Gleiche gilt für Zeichnungsereignisse: ` QWidget::update()` ruft ` postEvent()` auf, wodurch Flackern vermieden und die Geschwindigkeit erhöht wird, da mehrfache Neuzeichnungen vermieden werden.
postEvent() wird auch während der Objektinitialisierung verwendet, da das gepostete Ereignis in der Regel sehr bald nach Abschluss der Objektinitialisierung ausgelöst wird. Bei der Implementierung eines Widgets ist es wichtig zu beachten, dass Ereignisse bereits sehr früh in dessen Lebensdauer ausgelöst werden können; stellen Sie daher sicher, dass Sie in dessen Konstruktor die Membervariablen frühzeitig initialisieren, bevor die Möglichkeit besteht, dass es ein Ereignis empfängt.
Um Ereignisse eines benutzerdefinierten Typs zu erstellen, müssen Sie eine Ereignisnummer definieren, die größer als QEvent::User sein muss, und möglicherweise müssen Sie eine Unterklasse von ` QEvent ` erstellen, um spezifische Informationen über Ihr benutzerdefiniertes Ereignis zu übergeben. Weitere Details finden Sie in der Dokumentation zu „ QEvent “.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.