qt最小化托盘失焦问题

简介: qt通过QSystemTrayIcon很容易实现最小化托盘,但使用过程中发现一些特殊情况下的问题,就是会失去焦点。

qt通过QSystemTrayIcon很容易实现最小化托盘,但本人使用过程中发现一些特殊情况下的问题:

[1]qt4.8版本,在win及redhat6.5/5.5的32bit或64系统中静态编译的qt,在实现最小化托盘功能时

1)如果你的托盘菜单除了启动主窗体外,还能启动其它窗体

2)当主窗体最小化后,如果从托盘菜单进入其它窗体,这时焦点会跳转到该窗体

3)如果你主窗体处于最小化状态时,关闭了当前窗体,qt程序会捕捉不到焦点而退出程序

[2]qt4.8版本,在国产麒麟系统64位中,静态编译了qt,实现最小化托盘功能时

1)程序启动后,没有托盘显示,

2)当点击最小化托盘时,程序直接隐藏,也没有托盘出现

3)在进程查看中发现变成了僵死进程


示例解析:

void MainWindow::initTray()
{
    Qt::WindowFlags flags = 0;
    flags |= Qt::WindowMinMaxButtonsHint;
    flags |= Qt::CustomizeWindowHint;
    this->setWindowFlags(flags);
    this->setMouseTracking(true);

    QIcon icon = QIcon(":/images/iconApp.png");
    trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(icon);
    trayIcon->setToolTip(tr("ET1100-Browse"));
    QString titlec=tr("ET1100-Evt");
    QString textc=tr("app manage interface");
    trayIcon->show();
    trayIcon->showMessage(titlec,textc,QSystemTrayIcon::Information,5000);

    //添加单/双击鼠标相应
    connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this,SLOT(trayiconActivated(QSystemTrayIcon::ActivationReason)));

    //创建行为
    minimizeAction = new QAction(tr("Min(&I)"), this);
    connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
    restoreAction = new QAction(tr("Rec(&R)"), this);
    connect(restoreAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
    helpAction = new QAction(tr("Help(&H)"), this);//帮助窗体,会开启帮助手册窗口
    connect(helpAction, SIGNAL(triggered()), this, SLOT(helpView()));
    quitAction = new QAction(tr("Quit(&Q)"), this);
    connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));

    //创建右键弹出菜单
    trayIconMenu = new QMenu((QWidget*)QApplication::desktop());
    trayIconMenu->addAction(minimizeAction);
    trayIconMenu->addAction(restoreAction);
    trayIconMenu->addAction(helpAction);
    trayIconMenu->addSeparator();
    trayIconMenu->addAction(quitAction);
    trayIcon->setContextMenu(trayIconMenu);
}

void MainWindow::trayiconActivated(QSystemTrayIcon::ActivationReason reason)
{
    switch (reason)
    {
    case QSystemTrayIcon::Trigger:
        //单击托盘图标
    case QSystemTrayIcon::DoubleClick:
        //双击托盘图标
        this->showMaximized();
        this->raise();
        break;
    default:
        break;
    }
}

void MainView::changeEvent ( QEvent * event )
{
     //重点,窗口最小化时隐藏窗口,最小化到托盘   
    if(event->type()==QEvent::WindowStateChange)  
    {  
        //changeEvent会在窗口最小化之前调用,如果不加QTimer,   
        //我们把窗口隐藏了,但是Qt还以为窗口正要最小化,这样就会出错   
        if(windowState() & Qt::WindowMinimized){
            QTimer::singleShot(0, this, SLOT(hide()));
        }
    }  
    QWidget::changeEvent(event);  
}

在创建托盘菜单时,加入了一个帮助手册实现的窗体响应,可以在托盘菜单右键启动帮助窗体,窗体的启动及关闭实现函数:

void MainWindow::helpView()
{
    if (NULL!=assistant)
    {
        return;
    }
    //
    assistant = new Assistant("User-Manual.html");
    assistant->setMinimumSize(800, 600);
    connect(assistant,SIGNAL(closeNotify()),this,SLOT(closeHelpView()));
    assistant->show();
}

void MainWindow::closeHelpView()
{

    this->showMaximized();//激活主窗体防止失去焦点被qt内部退出
    this->raise();
    assistant->close();
    delete assistant;
    assistant=NULL;
}


在样例中是采用最简单的重新把已最小化的主窗体显示来获取焦点防止被退出,

如果没有这一步骤,在主窗体隐藏时关闭其它窗体会程序退出,,这样勉强内解决问题[1]

问题[2]是直接主窗体最小化及程序当掉,并残留在进程中

感觉无论是问题[1]还是问题[2],在调试时,没有捕捉到任何因为关闭其它窗体[1]或隐藏主窗体[2]引起qapp的关闭事件。

将this->showMaximized();注释掉,发现qt内部在处理事件时捕捉不到焦点进行主动关闭处理,,查看内部调用,

当其它窗体激活时,

        // then focus events
        if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
            QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason);
        } else if (QApplicationPrivate::active_window) {
            QWidget *w = QApplicationPrivate::active_window->focusWidget();
            if (w && w->isVisible() /*&& w->focusPolicy() != QWidget::NoFocus*/)
                w->setFocus(Qt::ActiveWindowFocusReason);
            else {
                w = QApplicationPrivate::focusNextPrevChild_helper(QApplicationPrivate::active_window, true);
                if (w) {
                    w->setFocus(Qt::ActiveWindowFocusReason);
                } else {
                    // If the focus widget is not in the activate_window, clear the focus
                    w = QApplicationPrivate::focus_widget;
                    if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus)
                        QApplicationPrivate::setFocusWidget(QApplicationPrivate::active_window, Qt::ActiveWindowFocusReason);
                    else if (!QApplicationPrivate::active_window->isAncestorOf(w))
                        QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason);
                }
            }
        }

焦点将被设置其它窗体

但是当关闭焦点窗体(如HelpView)就直接调用了

void MainWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)

{

......................................

case 3: _t->closeHelpView(); break;

.................................

}

激活了QApplication::~QApplication()退出程序。

因此,可以将其它窗体在主窗体进行调用激活,远离托盘菜单。





目录
相关文章
|
11月前
|
Windows 存储 Cloud Native
C++Qt windows系统托盘增加图标和功能
C++Qt windows系统托盘增加图标和功能
QT之Qml使用QSystemTrayIcon实现系统托盘
QT之Qml使用QSystemTrayIcon实现系统托盘
Qt 数据服务器、协议转换、系统托盘模块、CAN总线模块、反射内存卡模块
这个程序也不怎么复杂,就则一个界面,核心功能呢就是提供反射内存卡和CAN采集卡数据交互,其他的没有了。
136 0
Qt 数据服务器、协议转换、系统托盘模块、CAN总线模块、反射内存卡模块
|
自然语言处理
【Qt编程】基于Qt的词典开发系列<十一>系统托盘的显示
    本文主要讨论Qt中的系统托盘的设置。系统托盘想必大家都不陌生,最常用的就是QQ。系统托盘以简单、小巧的形式能让人们较快的打开软件。废话不多说,下面开始具体介绍。
1295 0
|
3月前
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
157 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
2月前
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
55 0
|
16天前
|
开发工具 C++
qt开发技巧与三个问题点
本文介绍了三个Qt开发中的常见问题及其解决方法,并提供了一些实用的开发技巧。
|
1月前
|
2月前
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
93 2