一、简介
Qt自带的例子/usr/lib64/qt4/examples/desktop/systray中详尽介绍了系统托盘的功能,在其基础上进行拓展,定制适合自己的系统托盘。
托盘菜单实现:QSystemTrayIcon+QMenu+QAction,有时需要加入QWidgetAction。
二、详解
1、代码
(1)systemtray.h
#ifndef SYSTEMTRAY_H
#define SYSTEMTRAY_H
#include <QSystemTrayIcon>
#include <QMenu>
#include <QAction>
#include <QApplication>
#include <QWidgetAction>
#include <QtGui>
class SystemTray : public QSystemTrayIcon
{
Q_OBJECT
public:
explicit SystemTray(QWidget *parent = 0);
~SystemTray();
void setParentWidget(QWidget *parent);
void setMiddleClickText(const QString &tips);
void setHideText(const QString &text);
void setToolTips(const QString &tips);
void startHideTips();
private:
void createActions();
void createTopWidget();
private slots:
void slotActivated(QSystemTrayIcon::ActivationReason reason);
void showParentWidget();
void slotHelpAction();
void slotClicked();
private:
QMenu *trayIconMenu;
QAction *showAction;
QAction *helpAction;
QAction *quitAction;
QWidget *parentWidget;
QString middleText;
QString toolTils;
QString hideText;
QMenu *funMenu;
QWidget *topWidget;
QWidgetAction *topWidgetAction;
QPushButton *showButton;
QPushButton *hideButton;
};
#endif // SYSTEMTRAY_H
(2)systemtray.cpp
#include <QUrl>
#include <QDebug>
#include <QDesktopServices>
#include "systemtray.h"
SystemTray::SystemTray(QWidget *parent)
: QSystemTrayIcon(parent)
, middleText("")
, toolTils("")
, hideText("")
{
parentWidget = parent;
createActions();
connect(this, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(slotActivated(QSystemTrayIcon::ActivationReason)));
}
SystemTray::~SystemTray()
{
}
void SystemTray::setParentWidget(QWidget *parent)
{
parentWidget = parent;
}
void SystemTray::setMiddleClickText(const QString &tips)
{
middleText = tips;
}
void SystemTray::setHideText(const QString &text)
{
hideText = text;
}
void SystemTray::setToolTips(const QString &tips)
{
this->setToolTip(tips);
}
void SystemTray::startHideTips()
{
this->showMessage(tr("提示信息:"), hideText, QSystemTrayIcon::Information, 2000);
}
void SystemTray::createActions()
{
this->setIcon(QIcon(":/tray.png"));
trayIconMenu = new QMenu();
createTopWidget();
funMenu = new QMenu();
showAction = new QAction(this);
helpAction = new QAction(this);
quitAction = new QAction(this);
funMenu->setIcon(QIcon(":/fun.png"));
showAction->setIcon(QIcon(":/show.png"));
helpAction->setIcon(QIcon(":/help.png"));
quitAction->setIcon(QIcon(":/quit.png"));
funMenu->setTitle(tr("功能"));
showAction->setText(tr("显示"));
helpAction->setText(tr("帮助"));
quitAction->setText(tr("退出"));
trayIconMenu->addAction(topWidgetAction);
//trayIconMenu->setFixedWidth(250);
trayIconMenu->addAction(showAction);
funMenu->addAction(helpAction);
trayIconMenu->addMenu(funMenu);
trayIconMenu->addSeparator();
trayIconMenu->addAction(quitAction);
this->setContextMenu(trayIconMenu);
connect(showAction, SIGNAL(triggered()), this, SLOT(showParentWidget()));
connect(helpAction, SIGNAL(triggered()), this, SLOT(slotHelpAction()));
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}
void SystemTray::createTopWidget()
{
topWidget = new QWidget();
topWidget->setStyleSheet("QWidget{background:#2FC77B;color:#000000}QPushButton:hover{color:#FFFFFF}QPushButton:disabled{color:#666666;border-style:flat;}");
topWidgetAction = new QWidgetAction(trayIconMenu);
QLabel *titleLabel = new QLabel();
titleLabel->setText(tr("系统托盘显示"));
showButton = new QPushButton();
showButton->setText(tr("显示"));
showButton->setFocusPolicy(Qt::NoFocus);
hideButton = new QPushButton();
hideButton->setText(tr("隐藏"));
hideButton->setFocusPolicy(Qt::NoFocus);
showButton->setCursor(Qt::PointingHandCursor);
hideButton->setCursor(Qt::PointingHandCursor);
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->addWidget(showButton);
hLayout->addStretch();
hLayout->addWidget(hideButton);
hLayout->setSpacing(10);
hLayout->setContentsMargins(0, 0, 0, 0);
QVBoxLayout *vLayout = new QVBoxLayout();
vLayout->addWidget(titleLabel);
vLayout->addLayout(hLayout);
vLayout->setSpacing(10);
vLayout->setContentsMargins(10, 5, 10, 5);
topWidget->setLayout(vLayout);
topWidgetAction->setDefaultWidget(topWidget);
connect(showButton, SIGNAL(clicked()), this, SLOT(slotClicked()));
connect(hideButton, SIGNAL(clicked()), this, SLOT(slotClicked()));
}
void SystemTray::slotActivated(QSystemTrayIcon::ActivationReason reason)
{
if (parentWidget) {
switch (reason) {
case QSystemTrayIcon::Trigger:
case QSystemTrayIcon::DoubleClick: {
if (parentWidget->isHidden() || parentWidget->windowState() == Qt::WindowMinimized) {
//showNormal(),showMinimized(),showMaxmized(),showFullScreen()
parentWidget->showNormal();
parentWidget->raise();
parentWidget->activateWindow();
}
else {
parentWidget->hide();
startHideTips();
}
break;
}
case QSystemTrayIcon::MiddleClick: {
if (!middleText.isEmpty()) {
this->showMessage(tr("提示信息:"), middleText, QSystemTrayIcon::Information, 3000);
}
break;
}
case QSystemTrayIcon::Context: {
if (parentWidget->isHidden() || parentWidget->windowState() == Qt::WindowMinimized) {
showAction->setText(tr("显示"));
showButton->setEnabled(true);
hideButton->setEnabled(false);
}
else {
showAction->setText(tr("隐藏"));
showButton->setEnabled(false);
hideButton->setEnabled(true);
}
break;
}
default:
break;
}
}
}
void SystemTray::showParentWidget()
{
if (showAction->text() == tr("显示")) {
parentWidget->showNormal();
parentWidget->raise();
parentWidget->activateWindow();
}
else {
parentWidget->hide();
startHideTips();
}
}
void SystemTray::slotHelpAction()
{
const QUrl AuthorUrl("https://www.gotosearch.info/");
//qDebug() << AuthorUrl.scheme();
//qDebug() << AuthorUrl.port();
QDesktopServices::openUrl(AuthorUrl);
}
void SystemTray::slotClicked()
{
QPushButton *button = qobject_cast<QPushButton *>(sender());
if (button == showButton) {
parentWidget->showNormal();
parentWidget->raise();
parentWidget->activateWindow();
}
else {
parentWidget->hide();
startHideTips();
}
}
(3)widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QtGui>
#include "systemtray.h"
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
protected:
void closeEvent(QCloseEvent *event);
private:
SystemTray *systemTray;
};
#endif // WIDGET_H
(4)widget.cpp
#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent, Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint)
{
setWindowTitle(tr("系统托盘"));
resize(400, 400);
move((QApplication::desktop()->width() - width())/2, (QApplication::desktop()->height() - height())/2);
systemTray = new SystemTray(this);
systemTray->setMiddleClickText(tr("系统托盘"));
systemTray->setToolTips(tr("应用程序系统托盘"));
systemTray->setHideText(tr("应用程序隐藏在系统托盘"));
systemTray->show();
}
Widget::~Widget()
{
}
void Widget::closeEvent(QCloseEvent *event)
{
if (systemTray->isVisible()) {
systemTray->startHideTips();
hide();
event->ignore();
}
}
(5)main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTextCodec *codec = QTextCodec::codecForName("utf8");
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
QMessageBox::critical(NULL, QObject::tr("系统托盘"), QObject::tr("不支持系统托盘"));
return 1;
}
Widget w;
w.show();
return a.exec();
}
2、运行效果图
四、总结
(1)注:系统托盘在centos下无法显示QAction的图标,并且提示message出现后鼠标滑过message在规定时间内不会消失。
(2)SystemTray是一个对QSystemTrayIcon的封装,可以直接拿到其他地方使用,但注意父类对象的传递。
(3)源码已经打包上传到csdn上(源码中有些问题在SystemTray::createActions()函数中,可对照文章修改),可登录下载(http://download.csdn.net/detail/taiyang1987912/8915693)。
(4)若有建议,请留言,在此先感谢!