Sur cette page

Le système d'événements

Dans Qt, les événements sont des objets dérivés de la classe abstraite ` QEvent `, qui représentent des actions survenues soit au sein d’une application, soit à la suite d’une activité externe dont l’application doit être informée. Les événements peuvent être reçus et gérés par n'importe quelle instance d'une sous-classe de ` QObject `, mais ils concernent tout particulièrement les widgets. Ce document décrit comment les événements sont diffusés et gérés dans une application type.

Comment les événements sont-ils diffusés ?

Lorsqu’un événement se produit, Qt crée un objet événement pour le représenter en construisant une instance de la sous-classe appropriée de ` QEvent `, puis le transmet à une instance particulière de ` QObject ` (ou à l’une de ses sous-classes) en appelant sa fonction ` event()`.

Cette fonction ne gère pas l’événement en lui-même ; en fonction du type d’événement transmis, elle appelle un gestionnaire d’événements pour ce type spécifique d’événement, puis renvoie une réponse indiquant si l’événement a été accepté ou ignoré.

Certains événements, tels que ` QMouseEvent ` et ` QKeyEvent`, proviennent du système de fenêtrage ; d’autres, tels que ` QTimerEvent`, proviennent d’autres sources ; d’autres encore proviennent de l’application elle-même.

Types d’événements

La plupart des types d’événements disposent de classes spécifiques, notamment QResizeEvent, QPaintEvent, QMouseEvent, QKeyEvent et QCloseEvent. Chaque classe hérite de QEvent et ajoute des fonctions propres à l’événement. Par exemple, QResizeEvent ajoute les méthodes size() et oldSize() pour permettre aux widgets de détecter les modifications apportées à leurs dimensions.

Certaines classes prennent en charge plusieurs types d’événements. La classe ` QMouseEvent ` prend en charge les pressions sur les boutons de souris, les doubles-clics, les déplacements et d’autres opérations associées.

Chaque événement est associé à un type, défini dans ` QEvent::Type`, et celui-ci peut servir de source pratique d’informations sur les types à l’exécution pour déterminer rapidement à partir de quelle sous-classe un objet événement donné a été construit.

Comme les programmes doivent réagir de manière variée et complexe, les mécanismes de diffusion des événements de Qt sont flexibles. La documentation relative à ` QCoreApplication::notify()` en donne un aperçu concis ; l’article du Qt Quarterly intitulé « Another Look at Events » en fait une reprise moins concise. Nous allons ici fournir des explications suffisantes pour 95 % des applications.

Gestionnaires d’événements

La méthode habituelle de diffusion d’un événement consiste à appeler une fonction virtuelle. Par exemple, l’événement « QPaintEvent » est diffusé en appelant la fonction ` QWidget::paintEvent()`. Cette fonction virtuelle est chargée de réagir de manière appropriée, généralement en rafraîchissant le widget. Si vous n’effectuez pas toutes les opérations nécessaires dans votre implémentation de la fonction virtuelle, vous devrez peut-être appeler l’implémentation de la classe de base.

Par exemple, le code suivant gère les clics du bouton gauche de la souris sur un widget de case à cocher personnalisé, tout en transmettant tous les autres clics de bouton à la classe de base QCheckBox:

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);
    }
}

Si vous souhaitez remplacer la fonction de la classe de base, vous devez tout implémenter vous-même. En revanche, si vous souhaitez simplement étendre les fonctionnalités de la classe de base, vous implémentez ce que vous souhaitez et appelez la classe de base pour obtenir le comportement par défaut dans tous les cas que vous ne souhaitez pas gérer.

Il arrive parfois qu’il n’existe pas de fonction spécifique à un événement, ou que celle-ci ne soit pas suffisante. L’exemple le plus courant concerne les pressions sur la touche Tab. Normalement, ` QWidget ` les intercepte pour déplacer le focus clavier, mais certains widgets ont besoin de la touche Tab pour leur propre fonctionnement.

Ces objets peuvent réimplémenter ` QObject::event()`, le gestionnaire d’événements général, et soit effectuer leur gestion d’événements avant ou après la gestion habituelle, soit remplacer complètement la fonction. Un widget très inhabituel qui interprète à la fois la touche Tab et dispose d’un événement personnalisé spécifique à l’application pourrait contenir la fonction ` event()` suivante :

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);
}

Notez que la fonction ` QWidget::event()` est toujours appelée pour tous les cas non gérés, et que la valeur de retour indique si un événement a été traité ; une valeur ` true ` empêche l’événement d’être transmis à d’autres objets.

Filtres d’événements

Il arrive parfois qu’un objet ait besoin d’examiner, voire d’intercepter, les événements transmis à un autre objet. Par exemple, les boîtes de dialogue souhaitent souvent filtrer les frappes de touches pour certains widgets, notamment pour modifier la gestion de la touche Entrée.

La fonction ` QObject::installEventFilter()` permet cela en configurant un filtre d’événements, ce qui fait qu’un objet filtre désigné reçoit les événements destinés à un objet cible dans sa fonction ` QObject::eventFilter()`. Un filtre d’événements traite les événements avant l’objet cible, ce qui lui permet de les inspecter et de les rejeter si nécessaire. Un filtre d’événements existant peut être supprimé à l’aide de la fonction ` QObject::removeEventFilter()`.

Lorsque l’implémentation de la méthode ` eventFilter()` de l’objet-filtre est appelée, celui-ci peut accepter ou rejeter l’événement, et autoriser ou refuser son traitement ultérieur. Si tous les filtres d’événements autorisent la poursuite du traitement d’un événement (en renvoyant chacun « false »), l’événement est envoyé à l’objet cible lui-même. Si l’un d’entre eux interrompt le traitement (en renvoyant « true »), l’objet cible et tous les filtres d’événements suivants ne verront pas du tout l’événement.

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;
}

Le code ci-dessus illustre une autre manière d’intercepter les événements de pression de la touche Tab envoyés à un widget cible particulier. Dans ce cas, le filtre traite les événements concernés et renvoie ` true ` pour empêcher leur traitement ultérieur. Tous les autres événements sont ignorés, et le filtre renvoie ` false ` pour permettre leur transmission au widget cible, via tout autre filtre d’événement installé sur celui-ci.

Il est également possible de filtrer tous les événements de l’ensemble de l’application en installant un filtre d’événements sur l’objet ` QApplication ` ou ` QCoreApplication `. Ces filtres d’événements globaux sont appelés avant les filtres spécifiques à un objet. Cette technique est très puissante, mais elle ralentit également la transmission de chaque événement dans l’ensemble de l’application ; il est généralement préférable d’utiliser les autres techniques décrites ici à la place.

Envoi d’événements

De nombreuses applications souhaitent créer et envoyer leurs propres événements. Vous pouvez envoyer des événements exactement de la même manière que la boucle d’événements native de Qt, en créant des objets d’événement adaptés et en les envoyant via QCoreApplication::sendEvent() et QCoreApplication::postEvent().

sendEvent() traite l’événement immédiatement. Lorsqu’elle renvoie une valeur, les filtres d’événements et/ou l’objet lui-même ont déjà traité l’événement. Pour de nombreuses classes d’événements, il existe une fonction appelée isAccepted() qui indique si l’événement a été accepté ou rejeté par le dernier gestionnaire appelé.

postEvent() place l'événement dans une file d'attente pour qu'il soit traité ultérieurement. Lors de la prochaine exécution de la boucle d'événements principale de Qt, celle-ci traite tous les événements placés en file d'attente, avec certaines optimisations. Par exemple, s'il y a plusieurs événements de redimensionnement, ils sont regroupés en un seul. Il en va de même pour les événements de dessin : ` QWidget::update()` appelle ` postEvent()`, ce qui élimine le scintillement et augmente la vitesse en évitant les redessinages multiples.

postEvent() est également utilisé lors de l’initialisation d’un objet, car l’événement posté sera généralement traité très peu de temps après la fin de l’initialisation de l’objet. Lors de l’implémentation d’un widget, il est important de garder à l’esprit que les événements peuvent être délivrés très tôt au cours de son cycle de vie ; par conséquent, dans son constructeur, veillez à initialiser les variables membres dès le début, avant qu’il n’y ait la moindre chance qu’il reçoive un événement.

Pour créer des événements d’un type personnalisé, vous devez définir un numéro d’événement, qui doit être supérieur à ` QEvent::User`, et vous devrez peut-être créer une sous-classe de ` QEvent ` afin de transmettre des informations spécifiques concernant votre événement personnalisé. Consultez la documentation « QEvent » pour plus de détails.

© 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.