2017年12月12日 星期二

Qt--如何使窗口隐藏/最小化到托盘

Qt中如何使窗口隐藏/最小化到托盘

Qt中如何实现自己的托盘功能,Qt自带的demo也很明了,这里我们就来实现自己的一个托盘。。。
功能:窗口最小化后或者点击“hide”按钮将窗口隐藏到托盘。
    通常最小化的窗口会在任务栏上显示一个按钮。当用户按一下这个按钮,窗口就还原了。这是一个被大多数桌面环境,比如WindowsKDEGNOME所采用的普遍设计。不过,因为任务栏通常只是桌面边上一小行,容纳不了很多按钮,用户通常希望把那些不常用的程序隐藏起来,只在通知栏显示一个小图标,要使用的时候再点击那个小图标恢复窗口。这种作法最典型的例子是QQWinamp
最基本的思路是拦截窗口的最小化事件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();  
}
        
}  

===========================================================
托盘图标,一个自己脑子出现很久的词,可惜自己都没动手去实现。最近看见的,听见的多了,自己也感兴趣就弄弄了,感觉还蛮简单了。
贴出效果图:



那么多功能,其实就一个类就搞定了,那就是QSystemTrayIcon
 头文件(主要 1.声明菜单相关动作 2.声明系统托盘对象,以及相关托盘槽函数 3.关闭事件)

  1. #ifndef SYSTEMTRAYICON_H  
  2. #define SYSTEMTRAYICON_H  
  3.   
  4. #include <QMainWindow>  
  5. #include <QMenu>  
  6. #include <QSystemTrayIcon>  
  7. #include <QCloseEvent>  
  8. namespace Ui {  
  9.     class SystemTrayIcon;  
  10. }  
  11.   
  12. class SystemTrayIcon : public QMainWindow  
  13. {  
  14.     Q_OBJECT  
  15.   
  16. public:  
  17.     explicit SystemTrayIcon(QWidget *parent = 0);  
  18.     ~SystemTrayIcon();  
  19.   
  20.     void CreatTrayMenu();  
  21.     void CreatTrayIcon();  
  22.   
  23.     QSystemTrayIcon *myTrayIcon;  
  24.   
  25.     QMenu *myMenu;  
  26.   
  27.     QAction *miniSizeAction;  
  28.     QAction *maxSizeAction;  
  29.     QAction *restoreWinAction;  
  30.     QAction *quitAction;  
  31.   
  32. private:  
  33.     Ui::SystemTrayIcon *ui;  
  34.   
  35. public slots:  
  36.     void iconActivated(QSystemTrayIcon::ActivationReason reason);  
  37.   
  38. protected:  
  39.     void closeEvent(QCloseEvent *event);  
  40.   
  41. };  
  42.   
  43. #endif // SYSTEMTRAYICON_H  



 源文件(1.创建上下文菜单 2.创建系统托盘,实现相关功能)---From  Qt  Assistant
 #include <QtGui>

  1. #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);
     }
  2.     


转: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


沒有留言:

張貼留言