Qt关闭窗口之小坑

2020-03-19 15:40:53 浏览数 (1)

❝开发中遇到了关闭窗口右上角"X"号居然不能正常退出程序,而是隐藏了窗口。究竟是什么回事呢? ❞

问题重现

  执行下列代码后点击右上角"X"号居然退出不了程序,而是隐藏了窗口。原以为会恢复正常退出程序的功能,其实不然。

代码语言:javascript复制
#include <QApplication>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    /* 切换到无标题栏模式 */
    w.setWindowFlag(Qt::ToolTip, true);
    
    // ...一些操作
    
    /* 恢复到有标题栏模式 */
    w.setWindowFlag(Qt::ToolTip, false);
    w.show();
    
    return a.exec();
}

  而正常操作下,下列代码点击右上角"X"号可以正常关闭窗口。

代码语言:javascript复制
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    w.show();
    
    return a.exec();
}

问题分析

  通过查看setWindowFlags的源码发现了这个函数adjustQuitOnCloseAttribute,似乎是可以改变了关闭按钮的状态,我们再进入函数一探究竟。

代码语言:javascript复制
void QWidgetPrivate::setWindowFlags(Qt::WindowFlags flags)
{
    Q_Q(QWidget);
    ...

    if ((q->data->window_flags | flags) & Qt::Window) {
        ...
        // 为了向后兼容,我们只在重新创建窗口时才更改Qt::WA_QuitOnClose属性值。
        adjustQuitOnCloseAttribute();
    }
    ...
}

adjustQuitOnCloseAttribute函数如下:

代码语言:javascript复制
void QWidgetPrivate::adjustQuitOnCloseAttribute()
{
    Q_Q(QWidget);

    if (!q->parentWidget()) {
        Qt::WindowType type = q->windowType();
        if (type == Qt::Widget || type == Qt::SubWindow)
            type = Qt::Window;
        if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
            q->setAttribute(Qt::WA_QuitOnClose, false);
    }
}

  可以看到,「当窗口类型不是Widget,Window,Dialog时则会设置关闭按钮不处理退出程序的操作。」

代码语言:javascript复制
if (type != Qt::Widget && type != Qt::Window && type != Qt::Dialog)
    q->setAttribute(Qt::WA_QuitOnClose, false);

问题解决

  设置setAttribute(Qt::WA_QuitOnClose, true)让其恢复关闭按钮退出的作用。

代码语言:javascript复制
#include <QApplication>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    /* 切换到无标题栏模式 */
    w.setWindowFlag(Qt::ToolTip, true);
    
    // ...一些操作
    
    /* 恢复到有标题栏模式 */
    w.setWindowFlag(Qt::ToolTip, false);
    /* 恢复关闭按钮的作用 */
    w.setAttribute(Qt::WA_QuitOnClose, true);
    w.show();
    
    return a.exec();
}

0 人点赞