QT如何实现后台运行(即最小化到右下角托盘)

2023年6月29日 0 By Majjcom

第一期:

用hello world简单的代码更容易看懂托盘的具体实现,一些细节问题,比如为什么提示消息没有显示在托盘上,如何在tip消息上增加图标等。

#include 

class myclass: public QWidget
{
public:
    myclass();

private:
    QPushButton *b1;
    QSystemTrayIcon *trayIcon;
};

myclass::myclass()
{
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
    setMinimumSize(200,100);
    setMaximumSize(200,100);
    b1 = new QPushButton("hello world",this);
    b1->setGeometry(20,20,160,40);
    QIcon icon = QIcon("./images/bad.svg");
    setWindowIcon(icon);
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(icon);
    trayIcon->setToolTip("a trayicon example");
    QString titlec = tr("Hello");
    QString textc = QString::fromLocal8Bit("Hello QT?");
    trayIcon->show();
    trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);
    setWindowTitle(tr("Systray"));
}

int main(int argc,char **argv)
{
    QApplication testc(argc,argv);
    myclass newc;
    newc.show();
    return testc.exec();
}

第二期:

进一步研究,加入点击托盘的响应,使提示信息显示在托盘上,托盘的右键菜单。

经验一:编译信号和槽 需要有.h .cpp这样的格式,否则不会生成相应的信号和槽;

经验二:信号和槽之间可以递参数,但是不允许函数直接给槽提供参数。

hello.h

#include 
class myclass: public QWidget
{
    Q_OBJECT
public:
    myclass();
private:
    QPushButton *b1;
    QSystemTrayIcon *trayIcon;
    char *msg;
    void showMessage(char *msg);
private slots:
    void showM();
    void iconActivated(QSystemTrayIcon::ActivationReason reason);
};

hello.cpp

#include 
#include "hello.h"
myclass::myclass()
{
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
    setMinimumSize(200,100);
    setMaximumSize(200,100);
    b1 = new QPushButton("hello world",this);
    b1->setGeometry(20,20,160,40);
    QIcon icon = QIcon("./images/bad.svg");
    setWindowIcon(icon);
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(icon);
    trayIcon->setToolTip("a trayicon example");
    trayIcon->show();
    setWindowTitle(tr("Systray"));
    connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
        this,SLOT(iconActivated(QSystemTrayIcon::ActivationReason))
    );
    connect(b1,SIGNAL(clicked()),this,SLOT(showM()));
}

void myclass::showM()
{
    QString titlec=tr("slot需要signal相同的参数进行传递");
    QString textc=QString::fromLocal8Bit("测试内容单击、双击、中键、按钮");
    trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);
}

void myclass::showMessage(char *msg)
{
    QString titlec=tr(msg);
    QString textc=QString::fromLocal8Bit("测试内容单击、双击、中键、按钮");
    trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);
}

void myclass::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason) {
    case QSystemTrayIcon::Trigger:
        showMessage("单击");
        break;
    case QSystemTrayIcon::DoubleClick:
        showMessage("双击啦");
        break;
    case QSystemTrayIcon::MiddleClick:
        showMessage("你用的是三轮鼠标还是滚轮鼠标啊");
        break;
    default:
        break;
    }
}

int main(int argc,char **argv)
{
    QApplication testc(argc,argv);
    myclass newc;
    newc.show();
    return testc.exec();
}

第三期:

那么最后我们把所有元素都结合在一起来实现这么一个托盘程序,比较上个例子我们增加了右键菜单并使它管理窗口的大小。
hello.h

#include 
class myclass: public QWidget
{
    Q_OBJECT
public:
    myclass();
private:
    QPushButton *b1;
    QSystemTrayIcon *trayIcon;
    char *msg;
    void showMessage(char *msg);
    void createActions();
    void createTrayIcon();
    QAction *minimizeAction;
    QAction *maximizeAction;
    QAction *restoreAction;
    QAction *quitAction;
    QMenu *trayIconMenu;
private slots:
    void showM();
    void iconActivated(QSystemTrayIcon::ActivationReason reason);
};

hello.cpp

#include 
#include "hello.h"
myclass::myclass()
{
    QTextCodec::setCodecForTr(QTextCodec::codecForName("GB2312"));
    setMinimumSize(200,100);
    b1 = new QPushButton("hello world",this);
    b1->setGeometry(20,20,160,40);
    QIcon icon = QIcon("./images/bad.svg");
    setWindowIcon(icon);
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(icon);
    trayIcon->setToolTip("a trayicon example");
    createActions();
    createTrayIcon();
    trayIcon->show();
    setWindowTitle(tr("Systray"));
    connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
    connect(b1,SIGNAL(clicked()),this,SLOT(showM()));
}

void myclass::showM()
{
    QString titlec=tr("slot需要signal相同的参数进行传递");
    QString textc=QString::fromLocal8Bit("测试内容单击、双击、中键、按钮"); 
    trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);
}

void myclass::showMessage(char *msg)
{
    QString titlec=tr(msg);
    QString textc=QString::fromLocal8Bit("测试内容单击、双击、中键、按钮"); 
    trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);
}

void myclass::iconActivated(QSystemTrayIcon::ActivationReason reason)
{
     switch (reason) {
     case QSystemTrayIcon::Trigger:
         showMessage("单击");
         break;
     case QSystemTrayIcon::DoubleClick:
         showMessage("双击啦");
         break;
     case QSystemTrayIcon::MiddleClick:
         showMessage("你用的是三轮鼠标还是滚轮鼠标啊");
         break;
     default:
         break;
     }
}

void myclass::createActions()
{
     minimizeAction = new QAction(tr("最小化 (&I)"), this);
     connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));

     maximizeAction = new QAction(tr("最大化 (&X)"), this);
     connect(maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));

     restoreAction = new QAction(tr("还原 (&R)"), this);
     connect(restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));

     quitAction = new QAction(tr("退出 (&Q)"), this);
     connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
}

void myclass::createTrayIcon()
{
     trayIconMenu = new QMenu(this);
     trayIconMenu->addAction(minimizeAction);
     trayIconMenu->addAction(maximizeAction);
     trayIconMenu->addAction(restoreAction);
     trayIconMenu->addSeparator();
     trayIconMenu->addAction(quitAction);
     trayIcon->setContextMenu(trayIconMenu);
}

int main(int argc,char **argv)
{
    QApplication testc(argc,argv);
    myclass newc;
    newc.show();
    return testc.exec();
}