La classe QSystemTrayIcon du framework Qt permet d'intégrer une application dans la zone de notification du système (systray). Elle est essentielle pour les outils tournant en arrière-plan ou nécessitant un accès rapide via un menu contextuel sans encombrer la barre des tâches principale.
Définition de l'interface (AppTrayWindow.h)
L'en-tête suivant définit une fenêtre principale capable de gérer les interactions avec l'icône système, incluant les notifications et les effets visuels comme le clignotement.
#ifndef APPTRAYWINDOW_H
#define APPTRAYWINDOW_H
#include <QMainWindow>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QAction>
#include <QTimerEvent>
QT_BEGIN_NAMESPACE
namespace Ui { class AppTrayWindow; }
QT_END_NAMESPACE
class AppTrayWindow : public QMainWindow
{
Q_OBJECT
public:
AppTrayWindow(QWidget *parent = nullptr);
~AppTrayWindow();
private slots:
void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
void toggleIconFlashing();
void showAppMessage();
void actionRestore();
void actionQuit();
protected:
void closeEvent(QCloseEvent *event) override;
void timerEvent(QTimerEvent *event) override;
private:
void initTraySystem();
Ui::AppTrayWindow *ui;
QSystemTrayIcon *trayIcon;
QMenu *trayMenu;
int blinkTimerId = -1;
bool isBlinking = false;
bool blinkState = false;
};
#endif // APPTRAYWINDOW_H
Implémentation de la logique (AppTrayWindow.cpp)
Le code ci-dessous illustre la configuration de l'icône, la gestion du menu contextuel et l'interception de l'événement de fermeture pour minimiser l'application au lieu de la quitter.
#include "AppTrayWindow.h"
#include "ui_AppTrayWindow.h"
#include <QCloseEvent>
#include <QMessageBox>
#include <QApplication>
AppTrayWindow::AppTrayWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::AppTrayWindow)
{
ui->setupUi(this);
initTraySystem();
}
AppTrayWindow::~AppTrayWindow()
{
delete ui;
}
void AppTrayWindow::initTraySystem()
{
trayIcon = new QSystemTrayIcon(this);
trayIcon->setIcon(QIcon(":/icons/app_main.png"));
trayIcon->setToolTip("Mon Application Qt");
// Construction du menu contextuel
trayMenu = new QMenu(this);
QAction *restoreAct = trayMenu->addAction("Restaurer");
trayMenu->addSeparator();
QAction *quitAct = trayMenu->addAction("Quitter");
connect(restoreAct, &QAction::triggered, this, &AppTrayWindow::actionRestore);
connect(quitAct, &QAction::triggered, this, &AppTrayWindow::actionQuit);
trayIcon->setContextMenu(trayMenu);
connect(trayIcon, &QSystemTrayIcon::activated, this, &AppTrayWindow::onTrayIconActivated);
trayIcon->show();
}
void AppTrayWindow::onTrayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason) {
case QSystemTrayIcon::Trigger:
// Action sur simple clic
break;
case QSystemTrayIcon::DoubleClick:
this->showNormal();
this->activateWindow();
break;
default:
break;
}
}
void AppTrayWindow::toggleIconFlashing()
{
if (isBlinking) {
killTimer(blinkTimerId);
blinkTimerId = -1;
isBlinking = false;
trayIcon->setIcon(QIcon(":/icons/app_main.png"));
} else {
blinkTimerId = startTimer(500);
isBlinking = true;
}
}
void AppTrayWindow::timerEvent(QTimerEvent *event)
{
if (event->timerId() == blinkTimerId) {
blinkState = !blinkState;
// Alternance entre une icône vide et l'icône réelle pour l'effet de flash
trayIcon->setIcon(blinkState ? QIcon(":/icons/app_main.png") : QIcon());
}
}
void AppTrayWindow::showAppMessage()
{
// Affiche une bulle d'information système
trayIcon->showMessage("Notification", "Une action importante a été détectée.",
QSystemTrayIcon::Information, 3000);
}
void AppTrayWindow::closeEvent(QCloseEvent *event)
{
if (trayIcon->isVisible()) {
QMessageBox::information(this, "Info", "L'application continue de s'exécuter en arrière-plan.");
this->hide();
event->ignore(); // Empêche la fermeture réelle de la fenêtre
}
}
void AppTrayWindow::actionRestore()
{
this->showNormal();
}
void AppTrayWindow::actionQuit()
{
qApp->quit();
}
Points techniques importants
- Visibilité : L'appel à
trayIcon->show()est impératif. Sans cela, l'icône ne sera jamais enregistrée auprès du gestionnaire de fenêtres du système d'exploitation. - Effet de clignotement : Pour simuler une alerte visuelle, on utilise un
QTimerqui alterne entre deux objetsQIcon. Notez que sur certains environnements (comme Windows), l'icône de remplacement ne doit pas être un chemin vide si l'on veut garantir un rendu propre ; il est préférable d'utiliser une icône tranpsarente. - Gestion de la fermeture : En surchargeant
closeEvent, on peut tranfsormer l'action de fermeture de la fenêtre (croix rouge) en une simple minimisation vers le systray. - Notifications système : La méthode
showMessages'appuie sur le centre de notification natif de l'OS. Si les notifications ne s'affichent pas, vérifiez les paramètres de confidentialité et de concentration du système d'exploitation.