系统托盘图标示例
系统托盘图标示例展示了如何在桌面环境的系统托盘中添加一个带有菜单和弹出消息的图标。
系统托盘图标截图
现代操作系统通常会在桌面上提供一个特殊区域,称为系统托盘或通知区域,长期运行的应用程序可在此显示图标和短信息。
本例由一个单独的类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; };
我们实现了几个用于响应用户交互的私有槽。其他私有函数只是为了简化构造函数而提供的方便函数。
托盘图标是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 用户注意:必须安装 Growl 通知系统,QSystemTrayIcon::showMessage() 才能显示消息。
QSystemTrayIcon 此外,Growl 还提供相应的 () 信号,当用户点击 () 显示的消息时,该信号就会发出。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 XML 中弹出消息框的最简单方法是调用一个相关的静态函数,如 () 。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
文件。
© 2025 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.