开发者社区> py_tty_0529> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

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()退出程序。

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





版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Qt的窗口的最大化。
1.window.showFullScreen()//此方法只对顶级窗口有效,对子窗口无效QT中窗口部件QWidget成员函数showFullScreen();是用于将窗口部件全屏显示,但是他只对窗口模式的部件有用。
630 0
窗口最小化到托盘
使用notifyIcon控件和contextMenuStrip控件实现 1.将notifyIcon控件和contextMenuStrip控件拖到form上 2.在FORM的FormClosing事件 // 取消关闭窗体 e.
917 0
C#实现窗口最小化到系统托盘
关键字:C# 最小化 托盘原文:http://www.cnblogs.com/txw1958/archive/2012/12/17/csharp-minimize-tray.html 先添加notifyicon控件notifyIcon1   using System; using System.
820 0
最小化程序到托盘
引用:http://blog.163.com/wwwyue_love/blog/static/16662945120101013111423304/ 所谓的“托盘”,在Windows系统界面中,指的就是下面任务条右侧,有系统时间等等的标志的那一部分。
887 0
C#实现WinForm窗口最小化到系统托盘
引用:http://www.cnblogs.com/xugang/archive/2007/12/19/1006005.html 1.设置WinForm窗体属性showinTask=false 2.加notifyicon控件notifyIcon1,为控件notifyIcon1的属性Icon添加一个icon图标。
558 0
c#中程序最小化到托盘
拖一个 notifyIcon控件到界面,名为 notifyIcon1           //窗体对应的事件         #region Form1_SizeChanged         private void For...
652 0
【转】c#最小化到托盘
下面是实现当点击最小化按钮时,程序缩到系统托盘中,双击系统托盘图标时,还原程序。 1、建个WinForm项目,其它操作略过。2、拉个NotifyIcon控件,将属性Visable设置成False,在Icon属性上选择一个图标文件。
1008 0
VC 制作系统托盘程序实现将窗口最小化到系统托盘
VC 制作系统托盘程序实现将窗口最小化到系统托盘 2008年01月11日 星期五 10:24 前段时间因为要用到系统拖盘,所以研究了一下,在这里记录一下,免得以后忘了 ^_^先在类中定义一个结构变量NOTIFYICONDATA pnid;然后在OnInitDialog进行初始化    pnid.
538 0
+关注
py_tty_0529
多年从事自动化系统研发,当前对物联网感兴趣
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载