QT最小化程式到托盤執行

2023-12-06 21:01:13

MinTray

說明

  • 實現程式關閉時最小化托盤的功能
  • 托盤實現顯示主頁面和退出的功能
  • 支援擴充套件,直接參照TrayIcon類即可,對外暴露介面
  • 單例實現,可複用

警告

  • 注:博主所有資源永久免費,若有幫助,請點贊轉發是對我莫大的幫助
  • 注:博主本人學習過程的分享,參照他人的文章皆會標註原作者
  • 注:本人文章非盈利性質,若有侵權請聯絡我刪除
  • 注:獲取資源或者諮詢問題請聯絡Q:2950319782
  • 注:博主本人很菜,文章基本是二次創作,大佬請忽略我的隨筆
  • 注:我會一步步分享實現的細節,若仍有問題聯絡我

GitHub

QtDemo下的Mintray

開發環境

  • win10系統
  • qtcreator4.11.1
  • QT版本:5.14.2

問題解決

需求

  • 程式在關閉的時候需要供使用者選擇是直接關閉程式還是最小化在托盤執行
  • 在托盤執行,程式主介面要隱藏
  • 托盤要提供最基本的顯示回主介面和退出程式的功能

結構

思路

  • 這裡主要為了實現關閉程式的時候實現程式托盤執行的demo,隨便建立一個widget程式Tray即可,重寫視窗的CloseEvent事件,處理關閉程式和最小化到托盤執行的功能
  • 使用QT自帶的QSystemTrayIcon來實現托盤的功能,單獨建立一個TrayIcon類來封裝,繼承自Object即可,不需要ui檔案,
  • 由於托盤這個類功能比較單一,而且是需要的 時候才建立,而且不能跟隨呼叫者的生存週期,這裡使用懶漢單例實現最好,最好使用智慧指標,省的發生記憶體漏失,在Tray視窗需要的時候才建立
  • 下面先來實現TrayIcon的單例,這裡使用返回static TrayIcon* 的Instance函數加獨佔智慧指標實現
  • 這裡我是選擇在CloseEvent事件中建立TrayIcon範例
  • 在TrayIcon類中,首先需要維持所屬的主表單mainWidget和托盤物件trayIcon,同時定義public的設定主表單函數setMainWidget來設定呼叫的主表單
  • 在TrayIcon的建構函式中範例化托盤物件trayIcon,設定圖示,完成初始設定
  • 到這裡只要設定托盤為可見,托盤就已經可以顯示出來了,但是沒法關閉程式和顯示主頁面了,下面來實現這兩個功能
  • 首先建立選單QMenu,因為這個選單功能主要是跟主視窗的互動,那麼在傳入主視窗的setMainWidget函數中設定選單為好
  • 先加上回顯主表單的功能,定義回顯函數showMainWidget
  • 下面處理關閉程式的功能,這裡最好是設定一個是關閉托盤還是關閉程式的標誌位,判斷一下最好
  • 選單功能處理後,是需要將選單和滑鼠右鍵繫結,否則不能處理相關操作
  • 最後處理一下托盤啟用程式,為了簡單,這裡雙擊和單擊都回顯主表單

關鍵程式碼

  • 重寫CloseEvent事件

    void Tray::closeEvent(QCloseEvent *event)
    {
        //彈出一個選擇按鈕,是否最小化程式到托盤執行
        QMessageBox::StandardButton button = QMessageBox::question(this,"提示","是否最小化到系統托盤", QMessageBox::Yes|QMessageBox::No,
    QMessageBox::Yes);
        //不關閉程式,最小化程式到托盤執行
        if(button == QMessageBox::Yes)
        {
            //設定托盤所屬的主表單
            TrayIcon::Instance()->setMainWidget(this);
            //忽略關閉事件
            event->ignore();
            //隱藏主視窗
            this->hide();
            //設定托盤可見
            TrayIcon::Instance()->setVisible(true);
            //設定提示訊息,看不見訊息的是電腦開啟了勿擾模式
            TrayIcon::Instance()->showMessage("自定義最小化托盤",
                                              "已最小化");
        }
        //關閉程式
        else
        {
            event->accept();
        }
    }
    
    
  • 實現懶漢單例

    //定義懶漢單例
    TrayIcon* TrayIcon::Instance()
    {
        if(self.isNull())
        {
            static QMutex mutex;
            QMutexLocker locker(&mutex);
            if(self.isNull())
            {
                self.reset(new TrayIcon);
            }
        }
        return self.data();
    }
    
  • 回顯主表單函數

    //定義顯示主介面的槽函數
    void TrayIcon::showMainWidget()
    {
        //有主表單
        if(mainWidget)
        {
            //顯示出來主表單
            mainWidget->showNormal();
            //重新聚焦主表單
            mainWidget->activateWindow();
        }
    }
    
  • 關閉程式函數

    //定義關閉的槽函數
    void TrayIcon::closeAll()
    {
        //隱藏,並刪掉,退出程式
        trayIcon->hide();
        trayIcon->deleteLater();
        qApp->exit();
    }
    
  • 設定呼叫的主表單,並繫結相關的功能

    //定義設定所屬的主表單
    void TrayIcon::setMainWidget(QWidget *mainWidget)
    {
        this->mainWidget = mainWidget;
        //給托盤加上選單功能
        menu->addAction("主介面",this,SLOT(showMainWidget()));
        //直接退出
        if(exitDirect)
        {
            menu->addAction("退出",this,SLOT(closeAll()));
        }
        else
        {
            menu->addAction("退出",this,SIGNAL(trayIconExit()));
        }
        //選單系結到右鍵
        trayIcon->setContextMenu(menu);
    
    }