Sur cette page

Exemple d'icône dans la barre d'état système

L'exemple d'icône de la barre d'état système montre comment ajouter une icône avec un menu et des messages contextuels à la barre d'état système d'un environnement de bureau.

Fenêtre contextuelle de la barre d'état système concernant un problème de réseau

Capture d'écran de l'icône de la barre d'état système

Les systèmes d'exploitation modernes prévoient généralement une zone spéciale sur le bureau, appelée barre d'état système ou zone de notification, où les applications en cours d'exécution peuvent afficher des icônes et de courts messages.

Cet exemple se compose d'une seule classe, Window, qui fournit la fenêtre principale de l'application (c'est-à-dire un éditeur pour l'icône de la barre d'état système) et l'icône associée.

L'éditeur de la barre d'état système permet de modifier divers paramètres tels que le titre, la durée et le message de la fenêtre contextuelle.

L'éditeur permet à l'utilisateur de choisir l'icône préférée et de définir le type et la durée du message de la bulle. L'utilisateur peut également modifier le titre et le corps du message. Enfin, l'éditeur propose une case à cocher permettant de contrôler si l'icône est effectivement affichée dans la barre d'état système ou non.

Définition de la classe Window

La classe Window hérite de QWidget:

class Window : public QDialog
{
    Q_OBJECT

public:
    Window();

    void setVisible(bool visible) override;

protected:
    void closeEvent(QCloseEvent *event) override;

private slots:
    void setIcon(int index);
    void iconActivated(QSystemTrayIcon::ActivationReason reason);
    void showMessage();
    void messageClicked();

private:
    void createIconGroupBox();
    void createMessageGroupBox();
    void createActions();
    void createTrayIcon();

    QGroupBox *iconGroupBox;
    QLabel *iconLabel;
    QComboBox *iconComboBox;
    QCheckBox *showIconCheckBox;

    QGroupBox *messageGroupBox;
    QLabel *typeLabel;
    QLabel *durationLabel;
    QLabel *durationWarningLabel;
    QLabel *titleLabel;
    QLabel *bodyLabel;
    QComboBox *typeComboBox;
    QSpinBox *durationSpinBox;
    QLineEdit *titleEdit;
    QTextEdit *bodyEdit;
    QPushButton *showMessageButton;

    QAction *minimizeAction;
    QAction *maximizeAction;
    QAction *restoreAction;
    QAction *quitAction;

    QSystemTrayIcon *trayIcon;
    QMenu *trayIconMenu;
};

Nous implémentons plusieurs slots privés pour répondre à l'interaction de l'utilisateur. Les autres fonctions privées ne sont que des fonctions de commodité fournies pour simplifier le constructeur.

L'icône de la barre d'état système est une instance de la classe QSystemTrayIcon. Pour vérifier si une barre d'état système est présente sur le bureau de l'utilisateur, appelez la fonction statique QSystemTrayIcon::isSystemTrayAvailable(). Associé à l'icône, nous fournissons un menu contenant les actions typiques minimize, maximize, restore et quit. Nous réimplémentons la fonction QWidget::setVisible() pour mettre à jour le menu de l'icône de la barre des tâches chaque fois que l'apparence de l'éditeur change, par exemple lors de l'agrandissement ou de la réduction de la fenêtre principale de l'application.

Enfin, nous avons réimplémenté la fonction closeEvent() de QWidget pour pouvoir informer l'utilisateur (lors de la fermeture de la fenêtre de l'éditeur) que le programme continuera à s'exécuter dans la barre des tâches jusqu'à ce que l'utilisateur choisisse l'entrée Quit dans le menu contextuel de l'icône.

Mise en œuvre de la classe de fenêtre

Lors de la construction du widget de l'éditeur, nous créons d'abord les divers éléments de l'éditeur avant de créer l'icône de la barre des tâches :

Window::Window()
{
    createIconGroupBox();
    createMessageGroupBox();

    iconLabel->setMinimumWidth(durationLabel->sizeHint().width());

    createActions();
    createTrayIcon();

    connect(showMessageButton, &QAbstractButton::clicked, this, &Window::showMessage);
    connect(showIconCheckBox, &QAbstractButton::toggled, trayIcon, &QSystemTrayIcon::setVisible);
    connect(iconComboBox, &QComboBox::currentIndexChanged,
            this, &Window::setIcon);
    connect(trayIcon, &QSystemTrayIcon::messageClicked, this, &Window::messageClicked);
    connect(trayIcon, &QSystemTrayIcon::activated, this, &Window::iconActivated);

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(iconGroupBox);
    mainLayout->addWidget(messageGroupBox);
    setLayout(mainLayout);

    iconComboBox->setCurrentIndex(1);
    trayIcon->show();

    setWindowTitle(tr("Systray"));
    resize(400, 300);
}

Nous nous assurons que l'application répond à la saisie de l'utilisateur en connectant la plupart des widgets de saisie de l'éditeur (y compris l'icône de la barre d'état système) aux emplacements privés de l'application. Mais notez la case à cocher de visibilité ; son signal toggled() est connecté à la fonction setVisible() de l'icône à la place.

void Window::setIcon(int index)
{
    QIcon icon = iconComboBox->itemIcon(index);
    trayIcon->setIcon(icon);
    setWindowIcon(icon);

    trayIcon->setToolTip(iconComboBox->itemText(index));
}

Le slot setIcon() est déclenché à chaque fois que l'index actuel de la boîte combobox change, c'est-à-dire à chaque fois que l'utilisateur choisit une autre icône dans l'éditeur. Notez qu'elle est également appelée lorsque l'utilisateur active l'icône de la barre des tâches avec le bouton gauche de la souris, ce qui déclenche le signal activated() de l'icône. Nous reviendrons prochainement sur ce signal.

La fonction QSystemTrayIcon::setIcon() définit la propriété icon qui contient l'icône de la barre d'état système. Sous Windows, la taille de l'icône de la barre d'état système est de 16x16 ; sous X11, la taille préférée est de 22x22. L'icône sera redimensionnée à la taille appropriée si nécessaire.

Notez que sous X11, en raison d'une limitation dans la spécification de la barre d'état système, les clics de souris sur les zones transparentes de l'icône sont propagés dans la barre d'état système. Si ce comportement est inacceptable, nous suggérons d'utiliser une icône sans transparence.

void Window::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason) {
    case QSystemTrayIcon::Trigger:
    case QSystemTrayIcon::DoubleClick:
        iconComboBox->setCurrentIndex((iconComboBox->currentIndex() + 1) % iconComboBox->count());
        break;
    case QSystemTrayIcon::MiddleClick:
        showMessage();
        break;
    default:
        ;
    }
}

Chaque fois que l'utilisateur active l'icône de la barre d'état système, celle-ci émet son signal activated() en passant la raison du déclenchement en paramètre. QSystemTrayIcon fournit l'énumération ActivationReason pour décrire la manière dont l'icône a été activée.

Dans le constructeur, nous avons connecté le signal activated() de notre icône à notre slot personnalisé iconActivated(): Si l'utilisateur a cliqué sur l'icône à l'aide du bouton gauche de la souris, cette fonction modifie l'image de l'icône en incrémentant l'index actuel de la combobox de l'icône, ce qui déclenche le slot setIcon() comme mentionné ci-dessus. Si l'utilisateur active l'icône à l'aide du bouton du milieu de la souris, cette fonction appelle le slot personnalisé showMessage():

void Window::showMessage()
{
    showIconCheckBox->setChecked(true);
    int selectedIcon = typeComboBox->itemData(typeComboBox->currentIndex()).toInt();
    QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon(selectedIcon);

    if (selectedIcon == -1) { // custom icon
        QIcon icon(iconComboBox->itemIcon(iconComboBox->currentIndex()));
        trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon,
                          durationSpinBox->value() * 1000);
    } else {
        trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), msgIcon,
                          durationSpinBox->value() * 1000);
    }
}

Lorsque le slot showMessage() est déclenché, nous récupérons d'abord l'icône du message en fonction du type de message choisi. L'énumération QSystemTrayIcon::MessageIcon décrit l'icône qui est affichée lorsqu'un message de type ballon est affiché. Ensuite, nous appelons la fonction showMessage() de QSystemTrayIcon pour afficher le message avec le titre, le corps et l'icône pendant la durée spécifiée en millisecondes.

Remarque à l'attention des utilisateurs de macOS : le système de notification Growl doit être installé pour que QSystemTrayIcon::showMessage() puisse afficher des messages.

QSystemTrayIcon a également le signal correspondant, messageClicked(), qui est émis lorsque l'utilisateur clique sur un message affiché par showMessage().

void Window::messageClicked()
{
    QMessageBox::information(nullptr, tr("Systray"),
                             tr("Sorry, I already gave what help I could.\n"
                                "Maybe you should try asking a human?"));
}

Dans le constructeur, nous avons connecté le signal messageClicked() à notre slot personnalisé messageClicked() qui affiche simplement un message à l'aide de la classe QMessageBox.

QMessageBox fournit une boîte de dialogue modale avec un court message, une icône et des boutons disposés en fonction du style actuel. Il prend en charge quatre niveaux de gravité : "Question", "Information", "Avertissement" et "Critique". La manière la plus simple de faire apparaître une boîte de message dans Qt XML est d'appeler l'une des fonctions statiques associées, par exemple QMessageBox::information().

Comme nous l'avons mentionné précédemment, nous réimplémentons quelques fonctions virtuelles de QWidget:

void Window::setVisible(bool visible)
{
    minimizeAction->setEnabled(visible);
    maximizeAction->setEnabled(!isMaximized());
    restoreAction->setEnabled(isMaximized() || !visible);
    QDialog::setVisible(visible);
}

Notre réimplémentation de la fonction QWidget::setVisible() met à jour le menu de l'icône de la barre des tâches chaque fois que l'apparence de l'éditeur change, par exemple lors de l'agrandissement ou de la réduction de la fenêtre principale de l'application, avant d'appeler l'implémentation de la classe de base.

void Window::closeEvent(QCloseEvent *event)
{
    if (!event->spontaneous() || !isVisible())
        return;
    if (trayIcon->isVisible()) {
        QMessageBox::information(this, tr("Systray"),
                                 tr("The program will keep running in the "
                                    "system tray. To terminate the program, "
                                    "choose <b>Quit</b> in the context menu "
                                    "of the system tray entry."));
        hide();
        event->ignore();
    }
}

Nous avons réimplémenté le gestionnaire d'événements QWidget::closeEvent() pour recevoir les événements de fermeture des widgets, en affichant le message ci-dessus aux utilisateurs lorsqu'ils ferment la fenêtre de l'éditeur. Nous devons éviter d'afficher le message et d'accepter l'événement de fermeture lorsque l'utilisateur a réellement l'intention de quitter l'application : c'est-à-dire lorsque l'utilisateur a cliqué sur "Quitter" dans la barre de menu, ou dans le menu contextuel de l'icône de la barre des tâches, ou en appuyant sur le raccourci Command+Q sur macOS.

En plus des fonctions et des slots présentés ci-dessus, nous avons également implémenté plusieurs fonctions de commodité pour simplifier le constructeur : createIconGroupBox(), createMessageGroupBox(), createActions() et createTrayIcon(). Voir le fichier desktop/systray/window.cpp pour plus de détails.

Exemple de projet @ code.qt.io

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