System Tray Icon Example展示了怎么样用菜单和弹出消息添加一个图标到桌面环境的系统托盘。现代操作系统通常在桌面提供一个特别的区域,称为系统托盘或通知区域。在这里长时间运行的应用可以展示图标和短信息。
本例子只有一个类:Window,提供应用程序窗口和关联的图标。
那个编辑器允许用户选择喜欢的图标和设置冒泡信息类型。用户也可以编辑信息的标题和内容。最后,这个编辑器提供一个checkBox控制是否在系统托盘里显示图标。
int main(int argc, char *argv[])
{
Q_INIT_RESOURCE(systray);
QApplication app(argc, argv);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
QMessageBox::critical(0, QObject::tr("Systray"),
QObject::tr("I couldn't detect any system tray "
"on this system."));
return 1;
}
QApplication::setQuitOnLastWindowClosed(false);
Window window;
window.show();
return app.exec();
}
QSystemTrayIcon在系统托盘里提供一个应用程序的图标。QSystemTrayIcon可以在下面平台使用:
1. 所有版本的windows
2. 所有freedesktop.org实现的有系统托盘的X11窗口管理器,包括最近版本的KDE,GNOME。
3. 所有版本的Mac OS X。
检查是否支持系统托盘: QSystemTrayIcon::isSystemTrayAvailable()
在系统托盘添加一个条目,创建一个QSystemTrayIcon(),调用setContextMenu()给Icon提供一个文本菜单,show()就让他显示出来,状态通知信息可以在任何时候展示出来通过使用showMessage()。当用户激活这个Icon就会发送activated()信号。
setQuitOnLastWindowClosed当上一个窗口关闭时,设置是否隐式地关闭应用程序。默认是true。即关闭。如果将这里注释掉,并且将Window::closeEvent中的event->ignore()注释掉。那么当我们关闭窗口时,弹出MessageBox,关闭MessageBox后,程序就不会在后台继续运行了,会默认的关闭掉。
class Window : public QDialog
{
Q_OBJECT
public:
Window();
void setVisible(bool visible);
protected:
void closeEvent(QCloseEvent *event);
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;
};
//! [0]
Window::Window()
{
createIconGroupBox(); // 创建Icon groupBox
createMessageGroupBox(); // 创建Message groupBox
iconLabel->setMinimumWidth(durationLabel->sizeHint().width()); // iconlabel的最小宽度
createActions(); // 创建作动菜单
createTrayIcon(); // 创建托盘图标
// showMessageButton点击信号连接showMessage()槽
connect(showMessageButton, SIGNAL(clicked()), this, SLOT(showMessage()));
// showIconCheckBox触发信号连接setVisible()槽
connect(showIconCheckBox, SIGNAL(toggled(bool)),
trayIcon, SLOT(setVisible(bool)));
// iconComboBox的当前项改变信号连接setIcon()槽
connect(iconComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(setIcon(int)));
// trayIcon的messageClicked信号连接Window的messageClicked
connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
// trayIcon的activated信号连接Window的iconActivated
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
// 窗体主布局
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(iconGroupBox);
mainLayout->addWidget(messageGroupBox);
setLayout(mainLayout);
// 设置iconComboBox的默认当期项为第二项
iconComboBox->setCurrentIndex(1);
trayIcon->show(); // 将托盘图标显示出来
setWindowTitle(tr("Systray")); // 窗体title
resize(400, 300); // 调整大小
}
//! [0]
//! [1]
// 设置Window的是否显示,如果显示,将最小化设置可用
void Window::setVisible(bool visible)
{
minimizeAction->setEnabled(visible);
maximizeAction->setEnabled(!isMaximized());
restoreAction->setEnabled(isMaximized() || !visible);
QDialog::setVisible(visible);
}
//! [1]
//! [2]
// 窗口关闭的时候,托盘图标如果是显示的弹出MessageBox消息,并将window对象窗体隐藏
void Window::closeEvent(QCloseEvent *event)
{
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(); // 忽视掉这个QCloseEvent相当于setAccepted(false)
}
}
//! [2]
//! [3]
// 设置图标槽
void Window::setIcon(int index)
{
QIcon icon = iconComboBox->itemIcon(index); // 获取Comobox中的当前项
trayIcon->setIcon(icon); // 设置托盘图标
setWindowIcon(icon); // 设置Window窗体图标
// 设置工具提示文字
// 这个提示在把鼠标放到图标上时就会显示出来
trayIcon->setToolTip(iconComboBox->itemText(index));
}
//! [3]
//! [4]
// QSystemTrayIcon::ActivationReason有五个枚举值
// Unknown:不明原因
// Context:上下文菜单被请求
// DoubleClick: 被鼠标双击
// Tirgger:被鼠标单击
// MiddleClick:被鼠标中键点击
void Window::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason) {
case QSystemTrayIcon::Trigger:
case QSystemTrayIcon::DoubleClick:
iconComboBox->setCurrentIndex((iconComboBox->currentIndex() + 1) // 触发的消息用于将ComboBox的项索引往后+1
% iconComboBox->count()); // 循环索引
break;
case QSystemTrayIcon::MiddleClick:
showMessage();
break;
default:
;
}
}
//! [4]
//! [5]
// 本程序核心功能槽
// showMessage()槽:让系统托盘的图标显示信息
void Window::showMessage()
{
QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon(
typeComboBox->itemData(typeComboBox->currentIndex()).toInt());
trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon,
durationSpinBox->value() * 1000);
}
//! [5]
//! [6]
// messageClicked()槽:弹出Messagebox
void Window::messageClicked()
{
QMessageBox::information(0, tr("Systray"),
tr("Sorry, I already gave what help I could.\n"
"Maybe you should try asking a human?"));
}
//! [6]
// 创建Icon groupBox
void Window::createIconGroupBox()
{
iconGroupBox = new QGroupBox(tr("Tray Icon"));
iconLabel = new QLabel("Icon:");
iconComboBox = new QComboBox;
// QIcon支持大部分常用格式
iconComboBox->addItem(QIcon(":/images/bad.svg"), tr("Bad"));
iconComboBox->addItem(QIcon(":/images/heart.svg"), tr("Heart"));
iconComboBox->addItem(QIcon(":/images/trash.svg"), tr("Trash"));
showIconCheckBox = new QCheckBox(tr("Show icon"));
showIconCheckBox->setChecked(true);
// 增加一个stretch在窗体宽变化时,通过改变它的宽来调整
QHBoxLayout *iconLayout = new QHBoxLayout;
iconLayout->addWidget(iconLabel);
iconLayout->addWidget(iconComboBox);
iconLayout->addStretch();
iconLayout->addWidget(showIconCheckBox);
iconGroupBox->setLayout(iconLayout);
}
// 创建Message groupBox
void Window::createMessageGroupBox()
{
messageGroupBox = new QGroupBox(tr("Balloon Message"));
typeLabel = new QLabel(tr("Type:"));
typeComboBox = new QComboBox;
// 为ComboBox添加四项
// 添加QSystemTrayIcon的四个标准图标
typeComboBox->addItem(tr("None"), QSystemTrayIcon::NoIcon);
// QWidget::style()返回QStyle
typeComboBox->addItem(style()->standardIcon(
QStyle::SP_MessageBoxInformation), tr("Information"),
QSystemTrayIcon::Information);
typeComboBox->addItem(style()->standardIcon(
QStyle::SP_MessageBoxWarning), tr("Warning"),
QSystemTrayIcon::Warning);
typeComboBox->addItem(style()->standardIcon(
QStyle::SP_MessageBoxCritical), tr("Critical"),
QSystemTrayIcon::Critical);
typeComboBox->setCurrentIndex(1);
durationLabel = new QLabel(tr("Duration:"));
// durationSpinBox设置消息停留的时间(秒)
durationSpinBox = new QSpinBox;
durationSpinBox->setRange(5, 60); // 范围
durationSpinBox->setSuffix(" s"); // 后缀
durationSpinBox->setValue(15); // 设置初始值
durationWarningLabel = new QLabel(tr("(some systems might ignore this "
"hint)"));
durationWarningLabel->setIndent(10); // 设置文本的缩进,如果为负数,0或没有设置,那就取决于frameWidth
titleLabel = new QLabel(tr("Title:")); // titleLabel
titleEdit = new QLineEdit(tr("Cannot connect to network")); // 创建titleEdit并初始化默认内容
bodyLabel = new QLabel(tr("Body:")); // bodyLabel
bodyEdit = new QTextEdit;
bodyEdit->setPlainText(tr("Don't believe me. Honestly, I don't have a " // 设置一个默认的文本内容
"clue.\nClick this balloon for details."));
showMessageButton = new QPushButton(tr("Show Message")); // 显示信息的button,并设为默认
showMessageButton->setDefault(true);
// 采用GridLayout设置以上的这些部件在messageGroupBox中的布局
QGridLayout *messageLayout = new QGridLayout;
messageLayout->addWidget(typeLabel, 0, 0);
messageLayout->addWidget(typeComboBox, 0, 1, 1, 2);
messageLayout->addWidget(durationLabel, 1, 0);
messageLayout->addWidget(durationSpinBox, 1, 1);
messageLayout->addWidget(durationWarningLabel, 1, 2, 1, 3);
messageLayout->addWidget(titleLabel, 2, 0);
messageLayout->addWidget(titleEdit, 2, 1, 1, 4);
messageLayout->addWidget(bodyLabel, 3, 0);
messageLayout->addWidget(bodyEdit, 3, 1, 2, 4);
messageLayout->addWidget(showMessageButton, 5, 4);
messageLayout->setColumnStretch(3, 1);
messageLayout->setRowStretch(4, 1);
messageGroupBox->setLayout(messageLayout);
}
// 创建托盘图标菜单
void Window::createActions()
{
minimizeAction = new QAction(tr("Mi&nimize"), this);
connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
maximizeAction = new QAction(tr("Ma&ximize"), this);
connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
restoreAction = new QAction(tr("&Restore"), this);
connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
quitAction = new QAction(tr("&Quit"), this);
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}
// 创建系统托盘图标,并给它设置一个菜单
void Window::createTrayIcon()
{
trayIconMenu = new QMenu(this);
trayIconMenu->addAction(minimizeAction);
trayIconMenu->addAction(maximizeAction);
trayIconMenu->addAction(restoreAction);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
trayIcon = new QSystemTrayIcon(this);
trayIcon->setContextMenu(trayIconMenu);
}