Qt中如何實作自己的托盤功能,Qt自帶的demo也很明了,這裡我們就來實作自己的一個托盤。。。
功能:視窗最小化後或者點選“hide”按鈕将視窗隐藏到托盤。
通常最小化的視窗會在工作列上顯示一個按鈕。當使用者按一下這個按鈕,視窗就還原了。這是一個被大多數桌面環境,比如Windows,KDE,GNOME所采用的普遍設計。不過,因為工作列通常隻是桌面邊上一小行,容納不了很多按鈕,使用者通常希望把那些不常用的程式隐藏起來,隻在通知欄顯示一個小圖示,要使用的時候再點選那個小圖示恢複視窗。這種作法最典型的例子是QQ和Winamp。
最基本的思路是攔截視窗的最小化事件changeEvent(),通過重寫changeEvent()即可。
“hide”按鈕的方式,是通過信号--槽來實作。
--------------------------------------------------------------------
void TrayMenu::createActions()
{
//建立托盤項
action_show = new QAction(this);
action_quit = new QAction(this);
action_login_home = new QAction(this);
action_help = new QAction(this);
action_about = new QAction(this);
action_check_update = new QAction(this);
action_setting = new QAction(this);
//設定托盤項圖示
action_show->setIcon(QIcon(":/icon/open"));
action_login_home->setIcon(QIcon(":/icon/home"));
action_help->setIcon(QIcon(":/icon/help"));
action_about->setIcon(QIcon(":/icon/about"));
action_check_update->setIcon(QIcon(":/icon/update"));
action_setting->setIcon(QIcon(":/icon/set"));
action_quit->setIcon(QIcon(":/icon/quit"));
//加載圖檔和提示
QIcon icon(":/images/sysTray.png");
systemTray = new QSystemTrayIcon(this);
systemTray->setIcon(icon);
systemTray->setToolTip("Hello, this is system tray!");
注意:這裡特别提醒,如果你的應用程式要移植到别的機器上,而且這個機器沒有裝Qt,QIcon的圖檔格式最好用png,而不要用ico等格式,否則托盤圖示不能顯示,會很麻煩。
//設定托盤想文本
action_show->setText(QString("顯示"));
action_quit->setText(QString("退出"));
action_login_home->setText(QString("登入網頁"));
action_help->setText(QString("幫助"));
action_about->setText(QString("關于"));
action_check_update->setText(QString("檢查更新"));
action_setting->setText(QString("設定"));
//添加菜單項
this->addAction(action_show);
this->addAction(action_setting);
this->addAction(action_login_home);
this->addSeparator();
this->addAction(action_help);
this->addAction(action_about);
this->addAction(action_check_update);
this->addSeparator();
this->addAction(action_quit);
action_setting->setVisible(false);
//設定信号連接配接(這裡僅列舉連接配接顯示視窗的信号)
QObject::connect(action_show, SIGNAL(triggered(bool)), this, SIGNAL(showWidget()));
}
LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent)
{
QSystemTrayIcon *system_tray = new QSystemTrayIcon();
//放在托盤提示資訊、托盤圖示
system_tray ->setToolTip(QString("我就是托盤"));
system_tray ->setIcon(QIcon(":/icon/login"));
TrayMenu *tray_menu = new TrayMenu();
system_tray->setContextMenu(tray_menu);
//點選托盤執行的事件
connect(system_tray , SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconIsActived(QSystemTrayIcon::ActivationReason)));
connect(tray_menu, SIGNAL(showWidget()), this, SLOT(showNormal()));
//顯示托盤
system_tray->show();
//托盤顯示提示資訊
system_tray->showMessage(QString("托盤标題"), QString("托盤顯示内容"));
}
void LoginDialog::iconIsActived(QSystemTrayIcon::ActivationReason reason)
{
switch(reason)
{
//點選托盤顯示視窗
case QSystemTrayIcon::Trigger:
{
showNormal();
break;
}
//輕按兩下托盤顯示視窗
case QSystemTrayIcon::DoubleClick:
{
showNormal();
break;
}
default:
break;
}
}
OK,這樣我們的托盤功能就Over了!
=============================================================================
另://關閉到托盤
void Widget::closeEvent(QCloseEvent *e)
{
e->ignore();
this->hide();
}
//最小化到托盤
void Widget::changeEvent(QEvent *e)
{
if((e->type()==QEvent::WindowStateChange)&&this->isMinimized())
{
QTimer::singleShot(100, this, SLOT(close()));
}
}
或者(me)
//點選視窗的“最小化"按鈕會調用此函數(系統預設)---已實作
void maxLinksGuard::changeEvent(QEvent * event )
{
if(event->WindowStateChange)
{
switch(this->windowState())
{
//點選“最小化”按鈕
case Qt::WindowMinimized:
this->hide();
this->setWindowFlags(Qt::Tool);//隐藏工作列上圖示
systemTray->show();//顯示托盤
systemTray->showMessage(windowTitle(),"Here is system,double click will show!");//提示
event->ignore();
break;
default:
break;
}
}
}
//托盤圖示事件--------已實作
void maxLinksGuard::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch (reason)
{
//單擊托盤
case QSystemTrayIcon::Trigger:
{
if(!this->isVisible())
{
this->setWindowFlags(Qt::Window); //顯示之前恢複
showNormal();
}
else
{
hide();
}
break;
}
//輕按兩下托盤---貌似不起作用
case QSystemTrayIcon::DoubleClick:
{
if(!this->isVisible())
{
this->setWindowFlags(Qt::Window); //顯示之前恢複
showNormal();
}
else
{
hide();
}
break;
}
case QSystemTrayIcon::MiddleClick:
{
break;
}
default: ;
}
}
//點選視窗的“關閉”按鈕觸發closeEvent事件(關閉應用程式)----已實作
void maxLinksGuard::closeEvent(QCloseEvent *event)
{
if (this->isVisible())
{
QMessageBox::critical(NULL,QObject::tr("Prompt:"),QObject::tr("Are you sure you want to kill/stop the MaxLinksGuard?"));
event->ignore();
}
else
{
event->accept();
}
}
===========================================================
托盤圖示,一個自己腦子出現很久的詞,可惜自己都沒動手去實作。最近看見的,聽見的多了,自己也感興趣就弄弄了,感覺還蠻簡單了。
貼出效果圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnL5QjM28VOwQzM2MTNzMTMvwVNy8CX0AjMxAjMvw1ckF2bsBXdvwFdl5mLuR2cj5Set1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
那麼多功能,其實就一個類就搞定了,那就是QSystemTrayIcon
頭檔案(主要 1.聲明菜單相關動作 2.聲明系統托盤對象,以及相關托盤槽函數 3.關閉事件)
[cpp] view plain copy print ?
- #ifndef SYSTEMTRAYICON_H
- #define SYSTEMTRAYICON_H
- #include <QMainWindow>
- #include <QMenu>
- #include <QSystemTrayIcon>
- #include <QCloseEvent>
- namespace Ui {
- class SystemTrayIcon;
- }
- class SystemTrayIcon : public QMainWindow
- {
- Q_OBJECT
- public:
- explicit SystemTrayIcon(QWidget *parent = 0);
- ~SystemTrayIcon();
- void CreatTrayMenu();
- void CreatTrayIcon();
- QSystemTrayIcon *myTrayIcon;
- QMenu *myMenu;
- QAction *miniSizeAction;
- QAction *maxSizeAction;
- QAction *restoreWinAction;
- QAction *quitAction;
- private:
- Ui::SystemTrayIcon *ui;
- public slots:
- void iconActivated(QSystemTrayIcon::ActivationReason reason);
- protected:
- void closeEvent(QCloseEvent *event);
- };
- #endif // SYSTEMTRAYICON_H
源檔案(1.建立上下文菜單 2.建立系統托盤,實作相關功能)---From Qt Assistant
#include <QtGui>
#include "window.h"
Window::Window()
{
createIconGroupBox();
createMessageGroupBox();
iconLabel->setMinimumWidth(durationLabel->sizeHint().width());
createActions();
createTrayIcon();
connect(showMessageButton, SIGNAL(clicked()), this, SLOT(showMessage()));
connect(showIconCheckBox, SIGNAL(toggled(bool)),
trayIcon, SLOT(setVisible(bool)));
connect(iconComboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(setIcon(int)));
connect(trayIcon, SIGNAL(messageClicked()), this, SLOT(messageClicked()));
connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addWidget(iconGroupBox);
mainLayout->addWidget(messageGroupBox);
setLayout(mainLayout);
iconComboBox->setCurrentIndex(1);
trayIcon->show();
setWindowTitle(tr("Systray"));
resize(400, 300);
}
void Window::setVisible(bool visible)
{
minimizeAction->setEnabled(visible);
maximizeAction->setEnabled(!isMaximized());
restoreAction->setEnabled(isMaximized() || !visible);
QDialog::setVisible(visible);
}
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();
}
}
void Window::setIcon(int index)
{
QIcon icon = iconComboBox->itemIcon(index);
trayIcon->setIcon(icon);
setWindowIcon(icon);
trayIcon->setToolTip(iconComboBox->itemText(index));
}
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:
;
}
}
void Window::showMessage()
{
QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon(
typeComboBox->itemData(typeComboBox->currentIndex()).toInt());
trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon,
durationSpinBox->value() * 1000);
}
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?"));
}
void Window::createIconGroupBox()
{
iconGroupBox = new QGroupBox(tr("Tray Icon"));
iconLabel = new QLabel("Icon:");
iconComboBox = new QComboBox;
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);
QHBoxLayout *iconLayout = new QHBoxLayout;
iconLayout->addWidget(iconLabel);
iconLayout->addWidget(iconComboBox);
iconLayout->addStretch();
iconLayout->addWidget(showIconCheckBox);
iconGroupBox->setLayout(iconLayout);
}
void Window::createMessageGroupBox()
{
messageGroupBox = new QGroupBox(tr("Balloon Message"));
typeLabel = new QLabel(tr("Type:"));
typeComboBox = new QComboBox;
typeComboBox->addItem(tr("None"), QSystemTrayIcon::NoIcon);
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 = 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);
titleLabel = new QLabel(tr("Title:"));
titleEdit = new QLineEdit(tr("Cannot connect to network"));
bodyLabel = new QLabel(tr("Body:"));
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"));
showMessageButton->setDefault(true);
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);
}
轉:http://blog.sina.com.cn/s/blog_a6fb6cc90101dddb.html
http://blog.csdn.net/qivan/article/details/7506306
另可參考:http://www.cnblogs.com/csuftzzk/archive/2013/01/25/2877283.html
http://www.qtcn.org/bbs/simple/?t15361.html
http://blog.csdn.net/learningstone/article/details/7932363
http://hi.baidu.com/sdink/item/85fa00d09864e01ed90e449a