首页 > 代码库 > QT Demo 之 window(5) window.qml

QT Demo 之 window(5) window.qml

在分析了main.cpp、Splash、Qt.quit()以及ScreenInfo之后,我们终于开始了正题:window.qml。

window.qml的主体结构

window.qml主体是一个QtObject,其中包含了4个子元素:palette、controlWindow、testWindow和splashWindow:

QtObject {
    property real defaultSpacing: 10
    property SystemPalette palette: SystemPalette { }

    property var controlWindow: Window {}

    property var testWindow: Window {}

    property var splashWindow: Splash {}
}

QtObject简述

The QtObject type is a non-visual element which contains only the objectName property.
It can be useful to create a QtObject if you need an extremely lightweight type to enclose a set of custom properties.

从文档中我们知道QtObject类型是一个超级简单基本的类型,只包含一个objectName的属性,但是可以通过风中一系列的自定义properties来扩展并完成需要的功能。这里的代码也是,在基本的QtObject下添加了4种扩展类型的properties和一个基本类型的property。

这里面也提到了另外一个词:lightweight,也就是在使用QtObject的时候主要不要做太复杂的操作和逻辑。这里面有一个很典型的例子,可以参考Qt5.3.2/Examples/Qt-5.3/quick/demos/samegame/content/Settings.qml的代码。

SystemPalette类型

The SystemPalette type provides access to the Qt application palettes. This provides information about the standard colors used for application windows, buttons and other features. These colors are grouped into three color groups: Active, Inactive, and Disabled. See the QPalette documentation for details about color groups and the properties provided by SystemPalette.
这里创建了一个基于SystemPalette的对象palette,主要的作用是在下面的controlWindow中使用palette.window来赋值给color属性:

        color: palette.window
这样使用的目的(个人猜测)是:获取背景窗口的颜色,来设置给当前窗口,以保持风格的一致性。

下面三组分别是palette.highlight、palette.dark和palette.text的运行效果对比:

看到这里,我们大致了解到SystemPalette的一些属性值是根据当前环境配置下的一些预定义的color数值。

controlWindow

controlWindow作为该应用的默认窗口,在Splash Screen之后就会显示controlWindow,具体界面见上面的运行效果中的任意一个。

先看一下controlWindow的程序代码结构:

    property var controlWindow: Window {
        width: visibilityLabel.implicitWidth * 1.2
        height: col.implicitHeight + defaultSpacing * 2
        color: palette.window
        title: "Control Window"
        Column {}
    }

配合代码以及运行效果,我们知道controlWindow就是一个Column的结构。其中宽度是按照中间的visibilityLabel的宽度乘以1.2;高度是按照整体的col的高度再加上一个间距值;颜色是上面提到的palette.window,在这里具体的值是#f0f0f0;因为我们这里是一个window,所以需要设置标题,此处设置标题为"Control Window"。

Column

之前的学习中有用到Column控件,此处不在展开,看一下Column中的具体元素:

        Column {
            id: col
            anchors.fill: parent
            anchors.margins: defaultSpacing
            spacing: defaultSpacing
            property real cellWidth: col.width / 3 - spacing
            Text { text: "Control the second window:" }
            Grid {}
            function visibilityToString(v) {}
            Text {}
            Rectangle {}
            ScreenInfo { }
        }
从代码和运行效果图对照来看,Column中包含以下几行元素:

  • Text,显示"Control the second window:"
  • Grid排列的两个Button和四个CheckBox
  • 定义visibilityToString(v)函数
  • 又是Text,显示第二个窗口的是否显示的状态
  • 通过Rectangle来模拟的一个黑色的分隔行
  • 调用ScreenInfo来显示Screen的信息

注:在Column中还有一个成员函数:visibilityToString(),会在第二个Text中调用到。

Column中子元素只有Shared.Button和Shared.CheckBox是新出现的两个空间,但是从命名上来看也不是属于系统的基本控件,如Text、Rectangle等等。

Shared.Button控件

                Shared.Button {
                    id: showButton
                    width: col.cellWidth
                    text: testWindow.visible ? "Hide" : "Show"
                    onClicked: testWindow.visible = !testWindow.visible
                }
Shared.Button的使用代码很简单,主要包括常见的id、width,以及Button上显示的文字和onClicked事件响应函数。

Shared.CheckBox控件

                Shared.CheckBox {
                    text: "Windowed"
                    height: showButton.height
                    width: col.cellWidth
                    Binding on checked { value: testWindow.visibility === Window.Windowed }
                    onClicked: testWindow.visibility = Window.Windowed
                }
相对于Shared.Button控件的使用方法上,多了一个Binding操作。其实在这里是非常好理解的,使用C代码可以表示如下:

if (testWindow.visibility == Window.Windowed)
	checked = true;
else
	checked = false;
这样,就即满足了单击的时候,修改testWindow.visibility属性,而且也完成,当testWindow.visibility属性改变(单击另外一个CheckBox)时,更新Shared.CheckBox的状态。

注:具体关于Binding的使用,后面在专门的章节中学习。

通过Rectangle来模拟的一个黑色的分隔线

如何绘制一条分割线,下面是一种实现方法:

            Rectangle {
                id: horizontalRule
                color: "black"
                width: parent.width
                height: 1
            }

如何在QML中定义和使用函数

            function visibilityToString(v) {
                switch (v) {
                case Window.Windowed:
                    return "windowed";
                case Window.Minimized:
                    return "minimized";
                case Window.Maximized:
                    return "maximized";
                case Window.FullScreen:
                    return "fullscreen";
                case Window.AutomaticVisibility:
                    return "automatic";
                case Window.Hidden:
                    return "hidden";
                }
                return "unknown";
            }
官方文档中没有给出具体的定义,但是从上面的示例中可以看出,Qml中函数的定义和JS中基本相同,都包含以下几点:

  • 弱数据类型,即参数和返回值都无需明确声明类型
  • 通过function关键字进行函数声明
  • 支持if/else、switch等分支处理方式

Window的visibility和visible属性

在controlWindow中除了上面使用的控件,其主要功能就是通过点击Button和CheckBox来改变testWindow的visibility和visible属性。下面我们就看一下这两个属性的具体说明。

visibility : QWindow::Visibility
    The screen-occupation state of the window.
    Visibility is whether the window should appear in the windowing system as normal, minimized, maximized, fullscreen or hidden.
    When a window is not visible its visibility is Hidden, and setting visibility to Hidden is the same as setting visible to false.

visible : bool
    Whether the window is visible on the screen.
    Setting visible to false is the same as setting visibility to Hidden.

结合程序的实际运行效果,我们知道:

  • 设置visibility属性为Windowed/Minimized/Maximized/FullScreen/AutomaticVisibility中任意一个都会使得visible属性为true,即显示Window
  • 直接修改visible属性为false,会使得visibility属性变为Hidden;但是当再次设置visible属性为true时,visibility属性会自动设为为原来的值。即从Windowed隐藏后,再次显示仍是Windowed。
  • 设置visibility属性为AutomaticVisibility时,会根据运行的平台不同实际上设置为Windowed/Minimized/Maximized/FullScreen四种中的具体一种,在PC平台上,会设置为Windowed。

testWindow 

testWindow的结构就比较简单,运行界面中元素也很少,先看一下代码的主结构:

    property var testWindow: Window {
        width: 320
        height: 240
        color: "#215400"
        title: "Test Window with color " + color
        flags: Qt.Window | Qt.WindowFullscreenButtonHint
        Rectangle {}
    }
testWindow中给出了具体的width和height;为了显示Rectangle,将整个Window的颜色设置为"#215400";设置了窗口的标题为"Test Window with color " + color;最后通过flags设置了窗口的Qt.Window和Qt.WindowFullscreenButtonHint属性。

Window.flags

The window flags control the window‘s appearance in the windowing system, whether it‘s a dialog, popup, or a regular window, and whether it should have a title bar, etc.

通过给Window设定不同的flags,使得其表现出不同的显示效果来。通过打印,我们得到controlWindow和testWindow的flags分别是:

  • 800F001:Qt::Window|Qt::WindowTitleHint|Qt::WindowSystemMenuHint|Qt::WindowMinimizeButtonHint|Qt::WindowMaximizeButtonHint|Qt::WindowCloseButtonHint
  • 80000001:Qt.Window | Qt.WindowFullscreenButtonHint

其中的Qt.Window不用多讲,表示这是一个Window,其它的还有Qt::Widget、Qt::Dialog等等。而对于controlWindow还有Title栏、SystemMenu栏、最小/最大/关闭按钮,而对于testWindow则是设置了Qt.WindowFullscreenButtonHint标记。而文档中Qt.WindowFullscreenButtonHint标记的说明是“On Mac OS X adds a fullscreen button.”,那么在Window系统上,testWindow则是相当于只设置了Qt.Window标记。

这里需要注意的一点是,虽然对于testWindow没有设置Qt::WindowTitleHint标记,也就是说没有标题栏,但是为什么又有title属性呢?其实title字段的值除了会显示在标题栏,还会再底部的任务栏处显示Window的标题,如下图所示:

testWindow中的子元素

testWindow中的Rectangle中的代码结构如下:

        Rectangle {
            anchors.fill: parent
            anchors.margins: defaultSpacing
            Text {}
            MouseArea {}
            Shared.Button {}
            Shared.Button {}
        }
其中涉及的Text、MouseArea以及刚才学习到的Shared.Button都是已经掌握的知识,此处不再赘述,具体的参照运行效果。

总结

本章节学到的知识:

  1. Window的visible和visibility属性及其改变后的效果
  2. SystemPalette系统调色板的使用
  3. 自定义控件Shared.Button和Shared.CheckBox的使用
  4. 如何在Qml中创建和使用函数
  5. Window中flags使用

这一章实际上就是重点演示了Window的visible和visibility属性以及改变其值后的表现,并没有讲解和演示Window的各种属性和设置等等。但是其中使用到的Shared.Button和Shared.CheckBox自定义控件却是一个新知识,该章节中并没有展开,后面有机会应该详细学习一下。

QT Demo 之 window(5) window.qml