System Tray Icon Example▲

Modern operating systems usually provide a special area on the desktop, called the system tray or notification area, where long-running applications can display icons and short messages.
This example consists of one single class, Window, providing the main application window (i.e., an editor for the system tray icon) and the associated icon.

The editor allows the user to choose the preferred icon as well as set the balloon message's type and duration. The user can also edit the message's title and body. Finally, the editor provides a checkbox controlling whether the icon is actually shown in the system tray, or not.
Window Class Definition▲
The Window class inherits 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;
}
;
We implement several private slots to respond to user interaction. The other private functions are only convenience functions provided to simplify the constructor.
The tray icon is an instance of the QSystemTrayIcon class. To check whether a system tray is present on the user's desktop, call the static QSystemTrayIcon::isSystemTrayAvailable() function. Associated with the icon, we provide a menu containing the typical minimize, maximize, restore and quit actions. We reimplement the QWidget::setVisible() function to update the tray icon's menu whenever the editor's appearance changes, e.g., when maximizing or minimizing the main application window.
Finally, we reimplement QWidget's closeEvent() function to be able to inform the user (when closing the editor window) that the program will keep running in the system tray until the user chooses the Quit entry in the icon's context menu.
Window Class Implementation▲
When constructing the editor widget, we first create the various editor elements before we create the actual system tray icon:
Window::
Window()
{
createIconGroupBox();
createMessageGroupBox();
iconLabel-&
gt;setMinimumWidth(durationLabel-&
gt;sizeHint().width());
createActions();
createTrayIcon();
connect(showMessageButton, &
amp;QAbstractButton::
clicked, this
, &
amp;Window::
showMessage);
connect(showIconCheckBox, &
amp;QAbstractButton::
toggled, trayIcon, &
amp;QSystemTrayIcon::
setVisible);
connect(iconComboBox, QOverload&
lt;int
&
gt;::
of(&
amp;QComboBox::
currentIndexChanged),
this
, &
amp;Window::
setIcon);
connect(trayIcon, &
amp;QSystemTrayIcon::
messageClicked, this
, &
amp;Window::
messageClicked);
connect(trayIcon, &
amp;QSystemTrayIcon::
activated, this
, &
amp;Window::
iconActivated);
QVBoxLayout *
mainLayout =
new
QVBoxLayout;
mainLayout-&
gt;addWidget(iconGroupBox);
mainLayout-&
gt;addWidget(messageGroupBox);
setLayout(mainLayout);
iconComboBox-&
gt;setCurrentIndex(1
);
trayIcon-&
gt;show();
setWindowTitle(tr("Systray"
));
resize(400
, 300
);
}
We ensure that the application responds to user input by connecting most of the editor's input widgets (including the system tray icon) to the application's private slots. But note the visibility checkbox; its toggled() signal is connected to the icon's setVisible() function instead.
void
Window::
setIcon(int
index)
{
QIcon icon =
iconComboBox-&
gt;itemIcon(index);
trayIcon-&
gt;setIcon(icon);
setWindowIcon(icon);
trayIcon-&
gt;setToolTip(iconComboBox-&
gt;itemText(index));
}
The setIcon() slot is triggered whenever the current index in the icon combobox changes, i.e., whenever the user chooses another icon in the editor. Note that it is also called when the user activates the tray icon with the left mouse button, triggering the icon's activated() signal. We will come back to this signal shortly.
The QSystemTrayIcon::setIcon() function sets the icon property that holds the actual system tray icon. On Windows, the system tray icon size is 16x16; on X11, the preferred size is 22x22. The icon will be scaled to the appropriate size as necessary.
Note that on X11, due to a limitation in the system tray specification, mouse clicks on transparent areas in the icon are propagated to the system tray. If this behavior is unacceptable, we suggest using an icon with no transparency.
void
Window::
iconActivated(QSystemTrayIcon::
ActivationReason reason)
{
switch
(reason) {
case
QSystemTrayIcon::
Trigger:
case
QSystemTrayIcon::
DoubleClick:
iconComboBox-&
gt;setCurrentIndex((iconComboBox-&
gt;currentIndex() +
1
) %
iconComboBox-&
gt;count());
break
;
case
QSystemTrayIcon::
MiddleClick:
showMessage();
break
;
default
:
;
}
}
Whenever the user activates the system tray icon, it emits its activated() signal passing the triggering reason as parameter. QSystemTrayIcon provides the ActivationReason enum to describe how the icon was activated.
In the constructor, we connected our icon's activated() signal to our custom iconActivated() slot: If the user has clicked the icon using the left mouse button, this function changes the icon image by incrementing the icon combobox's current index, triggering the setIcon() slot as mentioned above. If the user activates the icon using the middle mouse button, it calls the custom showMessage() slot:
void
Window::
showMessage()
{
showIconCheckBox-&
gt;setChecked(true
);
int
selectedIcon =
typeComboBox-&
gt;itemData(typeComboBox-&
gt;currentIndex()).toInt();
QSystemTrayIcon::
MessageIcon msgIcon =
QSystemTrayIcon::
MessageIcon(selectedIcon);
if
(selectedIcon ==
-
1
) {
// custom icon
QIcon icon(iconComboBox-&
gt;itemIcon(iconComboBox-&
gt;currentIndex()));
trayIcon-&
gt;showMessage(titleEdit-&
gt;text(), bodyEdit-&
gt;toPlainText(), icon,
durationSpinBox-&
gt;value() *
1000
);
}
else
{
trayIcon-&
gt;showMessage(titleEdit-&
gt;text(), bodyEdit-&
gt;toPlainText(), msgIcon,
durationSpinBox-&