前段时间在使用setWindowFlags方法时遇到了一个坑,具体情况是想通过窗口界面上一个checkBox来控制窗口当前状态是否置顶,而Qt提供了Qt::WindowStaysOnTopHint标志,能够让窗口始终保持在其他窗口前端,也就是将窗口置顶。

理论上,我们在勾选上checkBox之后将Qt::WindowStaysOnTopHint标志设置上,就会将窗口置顶,结果却将窗口隐藏了。那么为什么第二次调用setWindowFlags设置窗口标志位时窗口会隐藏了呢(实际上调用了hide()方法),下面就看一下具体是什么原因导致的。

Qt::WindowStaysOnTopHint

Informs the window system that the window should stay on top of all other windows . Note that on some window managers on X11 you also have to pass Qt::X11BypassWindowManagerHint for this flag to work correctly.

二、分析窗口隐藏原因

首先我们看一下代码,在构造函数中我们绑定checkBox,然后设置窗口属性。

this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
connect(ui.checkBox, SIGNAL(stateChanged(int)), this, SLOT(onStateChanged(int)));

checkBox状态变化槽函数

void onStateChanged(int state)
    if (state == Qt::Unchecked)
        // 未勾选时不置顶;
        this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
    else if (state == Qt::Checked)
        // 勾选时置顶;
        this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowStaysOnTopHint);

想要查找原因,那就得直接看Qt源码呀,所以就直接跟进了qwidget.cpp中的setWindowFlags方法。

调试之后,发现进入了setParent方法,我们仔细看一下,在setParent方法中确实会调用hide方法,那什么时候会调用呢,首先是判断窗口是否被创建,然后是窗口是否被隐藏,也就是如果窗口被创建并且没有被隐藏时会调用hide方法。下面是在构造函数中调用setWindowFlags时,wasCreated为false,也不会调用hide,而且当时窗口并未创建,所以在窗口未创建时无论调用多少次setWindowFlags方法,都会以最后一次调用时传入的参数为准。

下面是在窗口中勾选了checkBox,然后再次调用了setWindowFlags方法,此时满足窗口被创建并且没有被隐藏条件,所以这里调用了hide方法将窗口隐藏了,终于找到了原因。

那么也不是没有办法解决窗口置顶问题,windows提供了SetWindowPos方法解决了窗口置顶的问题。如果我们想一直保持窗口置顶状态也可以在窗口初始化时调用setWindowFlags方法传入Qt::WindowStaysOnTopHint标志即可使窗口置顶。

如果两个窗口都是置顶状态,如果层叠在一起也会相互覆盖。

解决办法一:

void onStateChanged(int state)
    if (state == Qt::Unchecked)
        ::SetWindowPos((HWND)this->winId(), HWND_NOTOPMOST, this->pos().x(), this->pos().y(), width(), height(), SWP_SHOWWINDOW);
    else if (state == Qt::Checked)
        ::SetWindowPos((HWND)this->winId(), HWND_TOPMOST, this->pos().x(), this->pos().y(), width(), height(), SWP_SHOWWINDOW);

解决办法二:

void onStateChanged(int state)
    if (state == Qt::Unchecked)
        // 未勾选时不置顶;
        this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint);
        // 如果当前窗口不可见,则显示出来;
        if (!this->isVisible())
            setVisible(true);
    else if (state == Qt::Checked)
        // 勾选时置顶;
        this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinimizeButtonHint | Qt::WindowStaysOnTopHint);
        // 如果当前窗口不可见,则显示出来;
        if (!this->isVisible())
            setVisible(true);

更新于2017_7_12。

Qt::WindowFlags Qt::Widget //是一个窗口或部件,有父窗口就是部件,没有就是窗口 Qt::Window //是一个窗口,有窗口边框和标题 Qt::Dialog //是一个对话框窗口 Qt::Sheet //是一个窗口或部件Macintosh表单 Qt::Dra... Qt怎样禁止用户最大化窗口Qt写一个窗口,如果继承QDialog,那窗口就只有关闭按钮,如果继承QWidget,那么就有关闭,最大化,最小化三个按钮,怎样才能让最大化按钮不可用,但是关闭和最小化可用呢? 要求要能够跨平台,是不是Qt无法做到这一点? ------解决方案-------------------- 当然做得到。 把窗体最大值设定为你当前窗口的值即可  ------解 Qt窗体若设置了运行后该窗体是无法进行移动和调整大小的,那要如何才能让它和普通窗体一样进行移动和调整其大小的呢?本文的方案还附加了一个自动吸附功能,各位如果不需要的话,可以移除。最后郑重提醒:别忘了在构造函数加上这句setMouseTracking(true);切记切记!!! 请注意,设置QWidget的窗口标志可能会影响QWidget的行为和性能,因此请仔细考虑您的需求和目标,以便选择正确的标志组合。Qt.Tool:指定QWidget为工具窗口Qt.Dialog:指定QWidget为对话框窗口。对话框窗口通常用于短期交互,如确认对话框或错误消息框。Qt.WindowStaysOnTopHint:指定QWidget始终显示在其他窗口的顶部。Qt.FramelessWindowHint:指定QWidget没有边框,标题栏或按钮。Qt.Widget:指定QWidget为常规窗口。     在进行Gui开发时,往往不会使用windows原生的窗口,而是需要进行自定义,此时就需要去除原有的窗口,以及上面相关的关闭按键,最小化最大化按键等; 这里使用函数:void setWindowFlags ( Qt::WindowFlags type ) Qt::WindowFlags 标志位 Qt去掉最大化最小化按钮和最大化 w.setWindowFlags(w.windowFlags()&~Qt::WindowMaximizeButtonHint&~Qt::WindowMinimizeButtonHint); w.showMaximized(); *******************  this->setWindowFlags(this->windowFlags()&~Qt QTsetwindowflags的属性总结 :setWindowFlags(Qt::CustomizeWindowHint);//设置窗口标题栏自定义 setWindowFlagsQt::WindowMinimizeButtonHint);//设置窗口的标题栏只有最小化的按钮 setWindowFlags(Qt::WindowCloseButtonHint );//设置窗口的标题栏只有关闭的按钮 setWindowFlagsQt::WindowStaysOnTopHint);//设置窗体一直. Qt学习之路(1):前言 Qt是一个著名的C++库——或许并不能说这只是一个GUI库,因为Qt十分庞大,并不仅仅是GUI。使用Qt,在一定程序上你获得的是一个“一站式”的 服务:不再需要研究STL,不再需要C++的,因为Qt有它自己的QString等等。或许这样说很偏激,但Qt确实是一个 “伟大的C++库”。 我们所使用Qt,确切地说也就是它的GUI编程部分。C++的GUI编程同Java 一、setWindowFlags窗口样式解析 在继承QWidget类的构造函数中,经常会出现这句: QWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()) QWidget *parent = Q_NULLPTR 是指父窗口部件的指定。 Qt::WindowFlags f = Qt::Windo...