当前位置:C++技术网 > 资讯 > Qt零基础教程:4.5 QWidget:windowFlags源码详解

Qt零基础教程:4.5 QWidget:windowFlags源码详解

更新时间:2015-08-11 16:35:44浏览次数:1+次

在这篇文章里面我们来分析一下这个windowFlags的内容

        在上面文章中我讲到Qt::WindowFlagstypehint两种,但是这个都是定义在一个枚举类型中,Qt中的定义如下:

****************************************************************************


enum WindowType {
        /*这部分是type类型*/
        Widget = 0x00000000,
        Window = 0x00000001,
        Dialog = 0x00000002 | Window,
        Sheet = 0x00000004 | Window,
        Drawer = Sheet | Dialog,
        Popup = 0x00000008 | Window,
        Tool = Popup | Dialog,
        ToolTip = Popup | Sheet,
        SplashScreen = ToolTip | Dialog,
        Desktop = 0x00000010 | Window,
        SubWindow = 0x00000012,
        ForeignWindow = 0x00000020 | Window,
        CoverWindow = 0x00000040 | Window,
 
 
        /*这部分是hint*/
        WindowType_Mask = 0x000000ff,
        MSWindowsFixedSizeDialogHint = 0x00000100,
        MSWindowsOwnDC = 0x00000200,
        BypassWindowManagerHint = 0x00000400,
        X11BypassWindowManagerHint = BypassWindowManagerHint,
        FramelessWindowHint = 0x00000800,
        WindowTitleHint = 0x00001000,
        WindowSystemMenuHint = 0x00002000,
        WindowMinimizeButtonHint = 0x00004000,
        WindowMaximizeButtonHint = 0x00008000,
         WindowMinMaxButtonsHint = WindowMinimizeButtonHint | 
         WindowMaximizeButtonHint,
        WindowContextHelpButtonHint = 0x00010000,
        WindowShadeButtonHint = 0x00020000,
        WindowStaysOnTopHint = 0x00040000,
        WindowTransparentForInput = 0x00080000,
        WindowOverridesSystemGestures = 0x00100000,
        WindowDoesNotAcceptFocus = 0x00200000,
 
        CustomizeWindowHint = 0x02000000,
        WindowStaysOnBottomHint = 0x04000000,
        WindowCloseButtonHint = 0x08000000,
        MacWindowToolBarButtonHint = 0x10000000,
        BypassGraphicsProxyWidget = 0x20000000,
        WindowOkButtonHint = 0x00080000,
        WindowCancelButtonHint = 0x00100000,
        NoDropShadowWindowHint = 0x40000000,
        WindowFullscreenButtonHint = 0x80000000
}; 


********************************************************************

然后有:


Q_DECLARE_FLAGS(WindowFlags, WindowType)


也即是说Qt::WindowFlags的实际内容就是Qt::WindowType。

下面我就来讲一下这两种。

***************************************************************************

首先我们看一下Qt中对于Qt::windowType的描述:


        首先这个有一个Qt::WindowType类型的枚举类型的,这里说这个枚举类型Qt::WindowType是用来指定窗口部件widget各种不同的窗口系统特性的。这些类型我们不经常用,但是确实是在某些情况下是必不可少的。他们中的某些类型还要取决于我们使用的系统的窗口管理系统是否支持这些类型。每种类型都有自己的一些特性。


***************************************************************************

        后面还有其他的一些特性,这些特性都是在顶层窗口上用来自定义窗口的。而且这些特性对其他的窗口的没有影响。


***************************************************************************

        这些窗口是用来自定义窗口的,如果要设计自定义窗口的话,必须要把

Qt::CustomizeWindowHint这标志位添加在上面。


上面的所有的宏定义都是定义在

enum WindowType{};

这个宏里面的。

 

        下面我们就来看一下QWidget中是怎么处理这个windowFlags的;

QWidgetData中有一个变量是用来存储windowFlags的,变量的声明如下:


Qt::WindowFlags window_flags;


        这个变量的类型就是Qt::WindowFlags,用来存储部件QWidget及其子类的windowFlags.

windowFlags的操作有两个函数:


void setWindowFlags(Qt::WindowFlags type);
inline Qt::WindowFlags windowFlags() const;


帮助中是这样的


一个事设置windowFlags,一个是获得windowFlags.

*******************************************************

        接下来我们就看一下Qt对外公布的源码中这两个函数的内容,先看:


inline Qt::WindowFlags windowFlags() const;



inline Qt::WindowFlags QWidget::windowFlags() const
{ return data->window_flags; }


        有人可能会问这个data是什么,简单的说,这个就相当于存储了所有的QWidget的私有变量,也就是说这个data就是一个小仓库,这个仓库里面保存了所有的QWidget的变量。然后这个data的类型是一个类,名字叫做


class QWidgetData{};


这个类里面没有函数,就当作结构体来看就可以了。

*************************************************************

        重头戏是


void setWindowFlags(Qt::WindowFlags type);


这个函数。


void QWidget::setWindowFlags(Qt::WindowFlags flags)
{
    if (data->window_flags == flags)
        return;
 
    Q_D(QWidget);
 
if ((data->window_flags | flags) & Qt::Window) {
        // the old type was a window and/or the new type is a window
        QPoint oldPos = pos();
        bool visible = isVisible();
        setParent(parentWidget(), flags);
 
        // if both types are windows or neither of them are, we restore
        // the old position
        if (!((data->window_flags ^ flags) & Qt::Window)
            && (visible || testAttribute(Qt::WA_Moved))) {
            move(oldPos);
        }
        // for backward-compatibility we change Qt::WA_QuitOnClose attribute value only when the window was recreated.
        d->adjustQuitOnCloseAttribute();
    } else {
        data->window_flags = flags;
    }
}


1.首先判断现有的data->window_flags和要设置的一不一样,

 if (data->window_flags == flags)

如果一样的话就直接返回


        下面要分两种情形进行讨论,

一种是现在要设置windowFlags的部件是一个窗口,

还有一种就是这个部件不是窗口。

2.如果是窗口的话,那么一定会有Qt::Window这个标志:

我们看一下对enum WindowType{};中这几个枚举的定义:

        Widget = 0x00000000,

        Window = 0x00000001,

        Dialog = 0x00000002 | Window,

        Sheet = 0x00000004 | Window,

        Drawer = Sheet | Dialog,

        Popup = 0x00000008 |Window,

        Tool = Popup | Dialog,

        ToolTip = Popup | Sheet,

        SplashScreen = ToolTip | Dialog,

        Desktop = 0x00000010 | Window,

        SubWindow = 0x00000012,

        ForeignWindow = 0x00000020 | Window,

        CoverWindow = 0x00000040 | Window,

Qt::Window是最低位为1其余位都为0的一个枚举量。然后很多其他的枚举量都有这个值:

        帮助中对这个枚举量的说明是他有标题栏,不管有没有父部件。如有一个部件没有父部件,那么这个标志一定是有的。所以现在如果是一个窗口的话,基本上就是其他窗口的父窗口的地位,地位是很高地

那么上面的

if ((data->window_flags | flags) & Qt::Window) {//这里按位或的意思就

                                                        //是说 这个窗口现在

//必须是Qt::Window类型的窗口,否则

//按位于都是零,那么就进不来这个if件语

//句中来了

//即新的新的窗口是一个window或者老

//的窗口是一个window

也就是说要么以前是一个窗口Qt::Window,要么现在有的flags中有Qt::Window,否则的话就进不来。一旦进来之后,

setParent(parentWidget(), flags);

设置相应的窗口,具体到setParent这个函数下面的文章中会说,反正现在可以设置标志位了。但是要记住的是,如果设置的部件正在桌面上显示的话,调用setWindowFlags这个函数之后还有调用show这个函数,即如下:

setWindowFlags(flags);
show();

3.如果这个部件不是窗口,即没有Qt::Window的话,那么就直接把flags赋给

data->window_flags = flags;

没有其余的操作。

******************************************************************************

        综上所述,可以通过setWindowFlags(flags)来设置标志位,然后如果设置的对象是一个窗口的话,并且窗口还在桌面上显示的话,要调用show()这个函数即:

setWindowFlags(flags);

show();

这个组合。如果不是窗口的,即设置的对象是其他的子部件的话,就直接设置的。

一般情况下我们要设置都是想设置窗口的windowFlags的,通过设置windowFlags来定制自己的窗口。

****************************************************************************

我们有一个关于编程语言交流的QQ群:372130111

有兴趣的可以加一下。