系统托盘图标示例
“系统托盘图标”示例演示了如何在桌面环境的系统托盘中添加一个带有菜单和弹出消息的图标。

系统托盘图标截图
现代操作系统通常在桌面上提供一个特殊区域,称为系统托盘或通知区,长期运行的应用程序可以在该区域显示图标和简短消息。
本示例由一个类Window 组成,该类提供主应用程序窗口(即系统托盘图标编辑器)和相关图标。

该编辑器允许用户选择所需的图标,并设置气泡消息的类型和显示时长。用户还可以编辑消息的标题和正文。最后,编辑器提供了一个复选框,用于控制图标是否实际显示在系统托盘中。
窗口类定义
Window 类继承自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;
};我们实现了几个私有槽(slot)来响应用户交互。其余私有函数仅为简化构造函数而提供的辅助函数。
托盘图标是QSystemTrayIcon 类的实例。若要检查用户桌面上是否存在系统托盘,请调用静态函数QSystemTrayIcon::isSystemTrayAvailable()。针对该图标,我们提供了一个菜单,其中包含典型的minimize 、maximize 、restore 和quit 操作。 我们重写了QWidget::setVisible() 函数,以便在编辑器的外观发生变化时(例如,当主应用程序窗口被最大化或最小化时)更新系统托盘图标的菜单。
最后,我们重写了QWidget 的closeEvent()函数,以便在关闭编辑器窗口时通知用户:程序将继续在系统托盘中运行,直到用户在图标的右键菜单中选择Quit 选项为止。
窗口类实现
在构建编辑器控件时,我们先创建各种编辑器元素,然后再创建实际的系统托盘图标:
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);
}我们通过将编辑器的大部分输入控件(包括系统托盘图标)连接到应用程序的私有槽,来确保应用程序能够响应用户输入。但请注意“可见性”复选框;其toggled()信号被连接到了图标的 setVisible()函数上。
void Window::setIcon(int index)
{
QIcon icon = iconComboBox->itemIcon(index);
trayIcon->setIcon(icon);
setWindowIcon(icon);
trayIcon->setToolTip(iconComboBox->itemText(index));
}每当图标组合框中的当前索引发生变化时,即用户在编辑器中选择另一个图标时,setIcon() 槽就会被触发。请注意,当用户用鼠标左键激活系统托盘图标时,该槽也会被调用,从而触发图标的activated()信号。我们稍后将再次讨论该信号。
QSystemTrayIcon::setIcon() 函数用于设置icon 属性,该属性存储实际的系统托盘图标。在 Windows 系统中,系统托盘图标的大小为 16x16;在 X11 系统中,推荐大小为 22x22。图标将根据需要缩放至适当尺寸。
请注意,在 X11 环境下,由于系统托盘规范的限制,鼠标点击图标中的透明区域时,点击操作会传递到系统托盘。如果无法接受这种行为,建议使用无透明区域的图标。
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:
;
}
}每当用户激活系统托盘图标时,它会发出activated()信号,并将触发原因作为参数传递。QSystemTrayIcon 提供了ActivationReason 枚举来描述图标被激活的方式。
在构造函数中,我们将图标的activated()信号连接到了自定义的iconActivated() 槽上:如果用户使用鼠标左键单击了图标,该函数会通过递增图标下拉列表的当前索引来更改图标图像,并如上所述触发setIcon() 槽。 如果用户使用鼠标中键激活图标,则会调用自定义的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);
}
}当showMessage()槽被触发时,我们会首先根据当前选定的消息类型获取相应的消息图标。QSystemTrayIcon::MessageIcon 枚举定义了显示气泡消息时对应的图标。随后,我们调用QSystemTrayIcon 的showMessage() 函数,以指定的毫秒数显示包含标题、正文和图标的消息。
macOS 用户请注意:QSystemTrayIcon::showMessage() 函数要显示消息,必须已安装 Growl 通知系统。
QSystemTrayIcon 此外,还提供了相应的messageClicked() 信号,当用户点击由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?"));
}在构造函数中,我们将messageClicked() 信号连接到我们自定义的messageClicked() 槽,该槽仅使用QMessageBox 类显示一条消息。
QMessageBox 该类提供了一个模态对话框,其中包含一条简短消息、一个图标以及根据当前样式布局的按钮。它支持四种严重级别:“问题”、“信息”、“警告”和“严重”。 在 Qt 中弹出消息框最简单的方法是调用相关的静态函数之一,例如QMessageBox::information()。
正如我们之前提到的,我们重写了 `QWidget` 的几个虚函数:
void Window::setVisible(bool visible)
{
minimizeAction->setEnabled(visible);
maximizeAction->setEnabled(!isMaximized());
restoreAction->setEnabled(isMaximized() || !visible);
QDialog::setVisible(visible);
}我们对QWidget::setVisible() 函数的重写会在编辑器的外观发生变化时(例如最大化或最小化主应用程序窗口时),在调用基类实现之前更新托盘图标的菜单。
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();
}
}我们重写了QWidget::closeEvent()事件处理程序以接收控件关闭事件,当用户关闭编辑器窗口时,会向其显示上述提示信息。 当用户确实打算退出应用程序时(即用户在菜单栏或系统托盘图标的右键菜单中点击了“退出”,或在 macOS 上按下了 Command+Q 快捷键),我们需要避免显示该提示并接受关闭事件。
除了上述讨论的函数和槽之外,我们还实现了一些便利函数以简化构造函数:createIconGroupBox() 、createMessageGroupBox() 、createActions() 和createTrayIcon() 。详情请参阅desktop/systray/window.cpp 文件。
© 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.