QSystemTrayIcon托盘程序关闭唯一的窗口,让QApplication不退出

问题

最近在做托盘程序,有这么个要求:启动程序时不打开任何界面界面,在系统托盘显示一个程序图标;右击图标时显示菜单,可选择显示弹窗和退出程序,并且点击“退出”程序才会结束程序。

我的托盘程序大致代码如下:

#include <QApplication>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QAction>
#include <QDialog>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QSystemTrayIcon *sti = new QSystemTrayIcon(&app);
    sti->setIcon(QIcon("logo.jpg"));
    sti->setToolTip("托盘程序");

    QMenu *menu = new QMenu();

    QAction *show_dialog = menu->addAction("弹窗");
    QAction *quit = menu->addAction("退出");

    app.connect(show_dialog, &QAction::triggered, [&](bool){
        QDialog d;
        d.exec();
    });
    app.connect(quit, &QAction::triggered, [&](bool){
        QApplication::instance()->quit();
    });


    sti->setContextMenu(menu);
    sti->show();

    return app.exec();
}

如果按照上面这么写的话,点击“弹窗”后显示一个窗口,这时将这个窗口关掉,整个托盘程序就直接就结束了,也就是退出了QApplication的事件循环(代码中的app.exec()),和我的想法背道而驰,我想要的是点击“退出”才会退出QApplication事件循环。
在网上查找解决方法基本上都是继承QDialog,然后重写closeEvent函数,将event忽略掉,这样虽然说不会退出QApplication事件循环,但是弹窗还一直存在,占用内存;而且调用hide()的话,程序也会直接结束。

我的解决方法

我试着写App继承QApplication,查看它退出时曾触发过什么事件:

class App : public QApplication{
public:
    App(int &argc, char **argv) : QApplication(argc, argv){
        installEventFilter(this);
    }

    bool eventFilter(QObject *watched, QEvent *event){
        qDebug() << watched->metaObject()->className() << event->type();
        return false;
    }
};

程序输出如下:
在这里插入图片描述
然后我在它退出前发现有触发过QEvent::Quit事件,于是我把它拦截了下来:

class App : public QApplication{
public:
    App(int &argc, char **argv) : QApplication(argc, argv){
        installEventFilter(this);
    }

    bool eventFilter(QObject *watched, QEvent *event){
        return (watched == this && event->type() == QEvent::Quit);
    }
};

经测试,这样做确实可以做到关闭唯一的窗口,QApplication不退出。但是还不够方便,于是我对着QApplication按下了F1,看到了这个:
在这里插入图片描述
果然还是要多看文档啊😭。

最后全部代码:

#include <QApplication>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QAction>
#include <QDialog>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    app.setQuitOnLastWindowClosed(false);

    QSystemTrayIcon *sti = new QSystemTrayIcon(&app);
    sti->setIcon(QIcon("logo.jpg"));
    sti->setToolTip("托盘程序");

    QMenu *menu = new QMenu();

    QAction *show_dialog = menu->addAction("弹窗");
    QAction *quit = menu->addAction("退出");

    app.connect(show_dialog, &QAction::triggered, [&](bool){
        QDialog d;
        d.exec();
    });
    app.connect(quit, &QAction::triggered, [&](bool){
        aApp->quit();
    });


    sti->setContextMenu(menu);
    sti->show();

    return app.exec();
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值