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 choses qui se sont produites soit au sein d'une application, soit à la suite d'une activité extérieure 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 sont particulièrement importants pour les widgets. Ce document décrit comment les événements sont délivrés et gérés dans une application typique.

Comment les événements sont délivrés

Lorsqu'un événement se produit, Qt XML crée un objet événement pour le représenter en construisant une instance de la sous-classe QEvent appropriée, et le délivre à 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 lui-même ; en fonction du type d'événement transmis, elle appelle un gestionnaire d'événement pour ce type d'événement spécifique et envoie une réponse selon que l'événement a été accepté ou ignoré.

Certains événements, tels que QMouseEvent et QKeyEvent, proviennent du système de fenêtres ; 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 ont des classes spéciales, notamment QResizeEvent, QPaintEvent, QMouseEvent, QKeyEvent et QCloseEvent. Chaque classe sous-classe QEvent et ajoute des fonctions spécifiques à l'événement. Par exemple, QResizeEvent ajoute size() et oldSize() pour permettre aux widgets de découvrir comment leurs dimensions ont été modifiées.

Certaines classes prennent en charge plus d'un type d'événement réel. QMouseEvent prend en charge les pressions sur les boutons de la souris, les doubles-clics, les déplacements et d'autres opérations connexes.

Chaque événement a un type associé, défini dans QEvent::Type, qui peut être utilisé comme une source pratique d'informations sur le type d'exécution pour déterminer rapidement la sous-classe à partir de laquelle un objet d'événement donné a été construit.

Puisque les programmes doivent réagir de manière variée et complexe, les mécanismes de livraison d'événements de Qt sont flexibles. La documentation de QCoreApplication::notify() raconte toute l'histoire de manière concise ; l'article de Qt Quarterly intitulé Another Look at Events (Un autre regard sur les événements ) la reprend de manière moins concise. Ici, nous en expliquerons suffisamment pour 95% des applications.

Gestionnaires d'événements

La façon normale de transmettre un événement est d'appeler une fonction virtuelle. Par exemple, QPaintEvent est délivré en appelant QWidget::paintEvent(). Cette fonction virtuelle est chargée de réagir de manière appropriée, normalement en repeignant le widget. Si vous n'effectuez pas tout le travail nécessaire 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 une case à cocher personnalisée tout en transmettant tous les autres clics à 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 mettre en œuvre vous-même. En revanche, si vous souhaitez uniquement étendre la fonctionnalité de la classe de base, vous implémentez ce que vous voulez et appelez la classe de base pour obtenir le comportement par défaut pour tous les cas que vous ne souhaitez pas traiter.

Parfois, il n'existe pas de fonction spécifique à l'événement, ou la fonction spécifique à l'événement n'est pas suffisante. L'exemple le plus courant concerne les appuis sur la touche Tab. Normalement, QWidget les intercepte pour déplacer le focus clavier, mais quelques widgets ont besoin de la touche Tab pour eux-mêmes.

Ces objets peuvent réimplémenter QObject::event(), le gestionnaire d'événements général, et gérer l'événement avant ou après la gestion habituelle, ou ils peuvent remplacer complètement la fonction. Un widget très inhabituel qui interprète Tab et possède un événement personnalisé spécifique à l'application peut 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 traité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 qu'un objet doive examiner, et éventuellement intercepter, les événements transmis à un autre objet. Par exemple, les boîtes de dialogue souhaitent souvent filtrer les pressions de touches pour certains widgets, par exemple pour modifier la gestion de la touche Return.

La fonction QObject::installEventFilter() permet de mettre en place un filtre d'événements, en faisant en sorte qu'un objet filtre désigné reçoive les événements d'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 d'inspecter et d'écarter les événements si nécessaire. Un filtre d'événements existant peut être supprimé à l'aide de la fonction QObject::removeEventFilter().

Lorsque l'implémentation eventFilter() de l'objet filtre est appelée, elle peut accepter ou rejeter l'événement, et autoriser ou refuser la poursuite du traitement de l'événement. 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), la cible et les filtres d'événements ultérieurs ne voient 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 montre une autre façon d'intercepter les événements d'appui sur une touche de tabulation envoyés à un widget cible particulier. Dans ce cas, le filtre traite les événements concernés et renvoie true pour arrêter leur traitement. Tous les autres événements sont ignorés et le filtre renvoie false pour leur permettre d'être envoyés au widget cible, par l'intermédiaire de tout autre filtre d'événement installé sur celui-ci.

Il est également possible de filtrer tous les événements de l'application entière 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 aux objets. Cette méthode est très puissante, mais elle ralentit également l'envoi de chaque événement dans l'ensemble de l'application ; les autres techniques décrites doivent généralement être utilisées à 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 de Qt XML en construisant des objets d'événements appropriés et en les envoyant avec QCoreApplication::sendEvent() et QCoreApplication::postEvent().

sendEvent() traite l'événement immédiatement. Lorsqu'il revient, 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 vous indique si l'événement a été accepté ou rejeté par le dernier gestionnaire appelé.

postEventLa fonction () place l'événement dans une file d'attente en vue d'un traitement ultérieur. La prochaine fois que la boucle événementielle principale de Qt s'exécute, elle distribue tous les événements affichés, avec quelques optimisations. Par exemple, s'il y a plusieurs événements de redimensionnement, ils sont comprimés en un seul. Il en va de même pour les événements de peinture : QWidget::update() appelle postEvent(), ce qui élimine le scintillement et augmente la vitesse en évitant les repeints multiples.

postEvent() est également utilisé lors de l'initialisation d'un objet, car l'événement affiché est généralement déclenché très rapidement après l'initialisation de l'objet. Lors de l'implémentation d'un widget, il est important de réaliser que les événements peuvent être délivrés très tôt dans sa vie. Ainsi, dans son constructeur, assurez-vous d'initialiser les variables membres très tôt, avant qu'il n'y ait la moindre chance de recevoir 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 sous-classer QEvent afin de transmettre des informations spécifiques sur votre événement personnalisé. Pour plus de détails, consultez la documentation de 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.