Qt Tray应用程序在菜单中执行任何操作后自行关闭



我是QT的新手,遇到了一个问题。

我决定尝试使用Qt和QSystemTrayIcon编写一个小应用程序。首先,我决定从Qt官方网站复制该示例。

https://doc.qt.io/qt-5/qtwidgets-desktop-systray-example.html?

这是我的头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QSystemTrayIcon>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QMenu *trayIconMenu;
QAction *launchAction;
QAction *quitAction;
QSystemTrayIcon *trayIcon;
public slots:
void changeEvent(QEvent*);
void trayIconActivated(QSystemTrayIcon::ActivationReason reason);
void trayActionExecute();
void setTrayIconActions();
void showTrayIcon();
};
#endif // MAINWINDOW_H

这是我的源代码文件:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setTrayIconActions();
this->showTrayIcon();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::showTrayIcon() {
trayIcon = new QSystemTrayIcon(this);
QIcon trayImage(":/images/trayIcon.png");
trayIcon->setIcon(trayImage);
trayIcon->setContextMenu(trayIconMenu);
connect(trayIcon, 
SLOT(activated(QSystemTrayIcon::ActivationReason)),
this, 
SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
trayIcon->show();
}
void MainWindow::trayActionExecute() {
QMessageBox::information(this, "TrayIcon", "Info text");
}
void MainWindow::trayIconActivated(QSystemTrayIcon::ActivationReason 
reason) {
switch (reason) {
case QSystemTrayIcon::Trigger:
case QSystemTrayIcon::DoubleClick:
this->trayActionExecute();
break;
default:
break;
}
}
void MainWindow::showMsg() {
QMessageBox::information(this, "Tray message", "Hello world!");
}
void MainWindow::setTrayIconActions() {
launchAction = new QAction("Launch", this);
quitAction = new QAction("Exit", this);
connect (launchAction, SIGNAL(triggered()), this, SLOT(showMsg()));
connect (quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
// Setting system tray's icon menu
trayIconMenu = new QMenu(this);
trayIconMenu -> addAction (launchAction);
trayIconMenu -> addAction (quitAction);
}
void MainWindow::changeEvent(QEvent *event) {
QMainWindow::changeEvent(event);
if (event->type() == QEvent::WindowStateChange) {
if (isMinimized()) {
this->hide();
}
}
}

当我在上下文菜单中执行任何操作时,应用程序就会关闭。 我认为重点是覆盖方法QCloseEvent,这将解决这种情况。所以,我重申它:

void MainWindow::closeEvent(QCloseEvent *event) {
#ifdef Q_OS_OSX
if (!event->spontaneous() || !isVisible()) {
return;
}
#endif
if (trayIcon->isVisible()) {
QMessageBox::information(this, tr("Systray"),
tr("The program will keep running in the "
"system tray"));
hide();
event->ignore();
}
}

可能出了什么问题?

谢谢。

可以通过最小化主窗口来重现该问题,该窗口会根据您的changeEvent()实现将其隐藏,然后单击系统托盘图标菜单中的"启动"。将显示消息框,然后应用程序将关闭。

这是由默认启用的称为QuitOnLastWindowClosed的 QT "功能"引起的。如果启用,应用程序将在最后一个非隐藏窗口关闭时退出 - 在您的示例中,这是由"启动"命令生成的消息框(计为一个窗口(!

您可以通过在创建QApplication后的某个时间点调用QApplication::setQuitOnLastWindowClosed(false);来解决此问题,例如,在可能设置应用程序的main.cpp中:

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(false);
MainWindow w;
w.show();
return a.exec();
}

附带说明一下,您在showTrayIcon()中的connect()语法是错误的:它应该拼写SIGNAL(activated(QSystemTrayIcon::ActivationReason))而不是SLOT(activated(QSystemTrayIcon::ActivationReason))

但我强烈建议改用新的信号/时隙语法(https://wiki.qt.io/New_Signal_Slot_Syntax(:

connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::trayIconActivated);

这样做的好处是在编译时而不是运行时显示任何错误(如未知信号/插槽或不兼容的参数(。

最新更新