QT开发(五十三)———QML基本元素

一、基本可视化项

可视元素具有几何坐标,会在屏幕上占据一块显示区域。

Item             基本的项元素,所有可视化项都继承Item

Rectangle        基本的可视化矩形元素

Gradient         定义一个两种颜色的渐变过程

GradientStop     定义个颜色,被Gradient使用

Image         在场景中使用位图

BorderImage     (特殊的项) 定义一张图片并当做边界

AnimatedImage    为播放动画存储一系列的帧

Text        在场景中使用文本

TextInput       显示可编辑为文本

IntValidatorint     验证器

DoubleValidator     double 验证器

RegExpValidator     验证字符串正则表达式

TextEdit    显示多行可编辑文本

1Item

    Item是所有可视元素中最基本的一个,是所有其它可视元素的父元素,所有其它可视元素都继承Item。Item本身没有任何绘制,作用是定义所有可视元素的通用属性

分组

属性

几何

x和y用于定义元素左上角的坐标,width和height则定义了元素的范围。z定义了元素上下的层叠关系。

布局

anchors(具有 left、right、top、bottom、vertical 和 horizontal center 等属性)用于定位元素相对于其它元素的margins的位置。

键盘处理

Key和KeyNavigation属性用于控制键盘;focus属性则用于启用键盘处理,也就是获取焦点。

  变形

提供scale和rotate变形以及更一般的针对 x、y、z 坐标值变换以及transformOrigin点的transform属性列表。

可视化

opacity属性用于控制透明度;visible属性用于控制显示/隐藏元素;clip属性用于剪切元素;smooth属性用于增强渲染质量。

状态定义

提供一个由状态组成的列表states和当前状态state属性;同时还有一个transitions列表,用于设置状态切换时的动画效果。

    除了定义通用属性,Item另外一个重要作用是作为其它可视元素的容器。

2Rectangle

    Rectangle继承了Item,并在Item的基础之上增加了填充色属性、边框相关的属性。为了定义圆角矩形,Rectangle还有一个radius属性。下面的代码定义了一个宽150像素、高100像素,浅金属蓝填充,红色4像素的边框的矩形

Rectangle
{
    id: rect
    width: 150
    height: 100
    color: "lightsteelblue"
    border
    {
        color: "#FF0000"
        width: 4
    }
    radius: 8
}

wKiom1hVTICjv9TdAAATpV5OY2A740.png

    QML中的颜色值可以使用颜色名字,也可以使用#十六进制的形式。

    Rectangle除了color属性外,还有一个gradient属性,用于定义使用渐变色填充

Rectangle
{
    width: 150
    height: 100
    gradient: Gradient
    {
        GradientStop { position: 0.0; color: "red" }
        GradientStop { position: 0.33; color: "yellow" }
        GradientStop { position: 1.0; color: "green" }
    }
    border.color: "slategray"
}

wKioL1hVTKKB8nERAAAKp5chJT4366.png

    gradient要求一个Gradient对象Gradient对象需要一个GradientStop的列表。所谓渐变,就是指定在某个位置必须是某种颜色,中间的过渡色则由计算而得。    GradientStop对象就是用于指定某个位置的颜色,需要两个属性:position和color。前者是一个 0.0 到 1.0 的浮点数,说明y轴方向的位置,例如元素的最顶部是0.0,最底部是1.0,介于最顶和最底之间的位置可以用一个浮点数表示,也就是一个比例;后者是position位置的颜色值。GradientStop { position: 0.33; color: "yellow" }说明在从上往下三分之一处是×××。

    Rectangle必须同时指定(显式地或隐式地)宽和高,否则不能在屏幕上显示出来。

3Text

    Text元素最重要的属性当然就是text属性。这个属性类型是string。Text元素会根据文本和字体计算自己的初始宽度和高度。字体则可以通过字体属性组设置(例如font.family、font.pixelSize等)。如果要设置文本颜色,只需要设置color属性。

    Text元素中的文本可以使用horizontalAlignment和verticalAlignment属性指定对齐方式。为了进一步增强文本渲染,可以使用style和styleColor两个属性。这两个属性允许我们指定文本的显示样式和样式的颜色。对于较长的文本,通常会选择在文本末尾使用 … ,elide属性允许指定 … 的显示位置。通过wrapMode属性可以指定换行模式。

Text
{
    width: 160
    height: 100
    text: "A very very long text"
    elide: Text.ElideRight
    style: Text.Sunken
    styleColor: '#FF4444'
    verticalAlignment: Text.AlignTop
    font
    {
        pixelSize: 24
    }
}

wKiom1hVTMfwLTLiAAAMa9eVUqs823.png

    Text元素的文本省略号位置在一行文本的右侧;具有一个#FF4444颜色的样式Sunken。Text元素的作用是显示文本,不会显示文本的任何背景。

4Image

    Image元素则用于显示图像。QML支持的图像格式有PNGJPG、GIF 和 BMP 等。可以直接给source属性一个URL来自动从网络加载图片,可以通过fillMode属性设置改变大小的行为。

    URL可以是本地路径,可以是网络路径。如果一个URL是网络的,QML 会自动从URL网络地址加载对应的资源。

Image
{
    x: 0;
    y: 0
    width: 97
    height: 120
    source: "http://ucenter.51cto.com/avatar.php?uid=9281927&size=middle"
    fillMode: Image.PreserveAspectCrop
    clip: true
}

wKiom1hVTObA6jTvAABxm2u1euM693.png

    Image.PreserveAspectCrop是等比例切割,需要同时设置clip属性,避免所要渲染的对象超出元素范围。

5TextInput

    TextInput是单行的文本输入框,支持验证器、输入掩码和显示模式等

import QtQuick 2.0
 
Rectangle {
    width: 200
    height: 80
    color: "blue"
 
    TextInput
    {
        id: input1
        x: 8; y: 8
        width: 96; height: 20
        focus: true
        text: "Text Input 1"
        KeyNavigation.tab: input2
    }
    TextInput
    {
        id: input2
        x: 8; y: 36
        width: 96; height: 20
        text: "Text Input 2"
        KeyNavigation.tab: input1
    }
}

    有两个TextInput,用户可以通过点击输入框改变焦点。如果想支持键盘导航,可以添加KeyNavigation附加属性。KeyNavigation是一个附加属性。当用户点击了指定的按键时,属性指定的组件就会获得焦点。普通的属性隶属于类型;附加属性一般用于修饰或补充目标类型。KeyNavigation.tab并不是TextInput的普通属性,是用来说明TextInput的一种特征。附加属性的一般语法是类型.属性名,类型就是KeyNavigation,属性名就是tab。

6TextEdit

    TextEdit是多行的文本编辑组件

import QtQuick 2.0
 
Rectangle {
    width: 200
    height: 80
    color: "blue"
 
    TextEdit
    {
        id: edit1
        x: 8; y: 8
        width: 96; height: 20
        focus: true
        text: "Text Edit 1"
        KeyNavigation.tab: edit2
    }
    TextEdit
    {
        id: edit2
        x: 8; y: 36
        width: 96; height: 20
        text: "Text Edit 2"
        KeyNavigation.tab: edit1
    }
}

7、IntValidator

    int 型验证器,和输入框结合后就是只能输入整型数据

import QtQuick 2.0
 
TextInput
{
    IntValidator{id: intval; bottom: 10; top: 100;}
    width: 100; height: 20;
    text: "";
    validator: intval;
}

8BorderImage

    BorderImage将一张图片分为9部分,当图片进行缩放的时候

    A.1 3 7 9位置的都不会进行缩放

    B. 2 8将根据属性horzontalTileMode 进行缩放

    C.4 6 将根据属性verticalTileMode 进行缩放

    D.5 将根据属性horzontalTileMode 和 verticalTileMode 进行缩放

import QtQuick 2.0
 
BorderImage 
{
    width: 180; height: 180
    border { left: 30; top: 30; right: 30; bottom: 30 }
    horizontalTileMode: BorderImage.Stretch
    verticalTileMode: BorderImage.Stretch
    source: "http://ucenter.51cto.com/avatar.php?uid=9281927&size=middle"
}

9DoubleValidator

    DoubleValidator 只能输入浮点数

TextInput
{
    DoubleValidator
    {
        id: intval
        decimals: 4
        bottom: 10
        top: 100
        notation: DoubleValidator.StandardNotation
    }
    width: 100; height: 20;
    text: "";
    validator: intval;
}

10RegExpValidator

    RegExpValidator使用正则表达式

TextInput
{
    // 使用一个正则表达式来控制输入的字符串
    // /^[a-zA-Z]{1}[0-1]{0,2}[a-z]{1,3}$/ 表示 开始位置必须是一个大写或小写字母
    // 接下来是0~2个的数字而且是0或1,在接下来是1~3个的小写字母
    RegExpValidator{id: intval; regExp:/^[a-zA-Z]{1}[0-1]{0,2}[a-z]{1,3}$/;}
    width: 100; height: 20;
    text: "";
    validator: intval;
}

11AnimatedImage

    AnimatedImage 主要用于播放gif图片

import QtQuick 2.0
 
Rectangle
{
    width: animation.width; height: animation.height + 8
    AnimatedImage
    {
        id: animation
        source: "animation.gif"
    }
    Rectangle
    {
        property int frames: animation.frameCount
        width: 4; height: 8
        x: (animation.width - width) * animation.currentFrame / frames
        y: animation.height
        color: "red"
    }
}

二、基本的交互项

不可视元素(例如Timer)通常提供一种作用于可视元素的功能。

    MouseArea    鼠标句柄交互

    FocusScope      键盘焦点句柄

    Flickable       提供一种浏览整张图片的一部分的效果

    Flipable提供一个平面,可以进行翻转看前面或后面

1MouseArea

    MouseArea用于用户交互,是一个不可见的矩形区域,用于捕获鼠标事件。通常会将MouseArea元素与一个可视元素结合起来使用,以便可视元素能够与用户交互。

Rectangle
{
    id: rect
    x: 0;
    y: 0
    width: 150;
    height: 100
    color: "red"
    MouseArea
    {
        anchors.fill:parent
        onClicked:
        {
            Qt.quit();
        }
    }
}

wKioL1hVTSGjqdIKAAAKKs6gq0k986.png


    MouseArea将可视化展示与用户输入控制解耦,可以显示一个较小的元素,但有一个很大的可交互区域,以便在界面显示与用户交互之间找到一个平衡(如果在移动设备上,较小的区域非常不容易被用户成功点击。苹果公司要求界面的交互部分最少要有 40 像素以上,才能够很容易被手指点中)。

2FocusScope

Widget.qml文件:

import QtQuick 2.0
 
FocusScope
{
    id: scope
    property alias color: rectangle.color
    x: rectangle.x; y: rectangle.y
    width: rectangle.width; height: rectangle.height
    Rectangle
    {
        id: rectangle
        anchors.centerIn: parent
        color: "lightsteelblue"
        width: 175; height: 30
        radius: 10; antialiasing: true
        Text { id: label; anchors.centerIn: parent }
        focus: true
        Keys.onPressed:
        {
            if (event.key == Qt.Key_A)
                label.text = 'Key A was pressed'
            else if (event.key == Qt.Key_B)
                label.text = 'Key B was pressed'
            else if (event.key == Qt.Key_C)
                label.text = 'Key C was pressed'
        }
    }
    MouseArea
    {
        anchors.fill: parent;
        onClicked: { scope.focus = true }
    }
}

使用Widget组件:

import QtQuick 2.0
 
Rectangle
{
    id: widget
    width: 240; height: 150
    color:"white";
 
    Column
    {
        anchors.centerIn: parent; spacing: 15
        Widget
        {
            color: "lightblue"
        }
        Widget
        {
            focus:true
            color: "palegreen"
        }
    }
}

3、Flickable

    QML中提供了一个Flickable元素,可以将其子项目设置在一个可以拖曳和弹动的界面上,使得子项目的视图可以滚动。Flickable不会自动剪裁它的内容,如果不是将它用作全屏项目,可以将clip属性设置为true来隐藏超出区域的内容。

import QtQuick 2.0
 
Flickable
{
    width: 200; height: 200
    contentWidth: p_w_picpath.width
    contentHeight: p_w_picpath.height
    //interactive: false    //禁止拖动弹动功能
    Image
    {
        id: p_w_picpath
        source: "http://ucenter.51cto.com/avatar.php?uid=9281927&size=middle"
    }
}

4Flipable

    Flipable是一个可以明显在其正面和反面之间进行翻转的项目,同时使用Rotation、State和Transition等元素来产生翻转效果。front和back分别用来保存要显示在Flipable项目的正面和反面的项目。Flipable有一个flipped布尔值属性,每当在Flipable中的MouseArea上单击鼠标时都会切换该属性的值。当flipped为true时,项目变为back状态,在这个状态,Rotation的angle属性改变为180°来产生一个翻转效果。当flipped为false时,项目恢复到默认状态,angle的值为 0。

import QtQuick 2.6
 
Flipable
{
    id: flipable
    width: 240; height:240
    property bool flipped: false
    //正面、反面图片资源
    front: Image{source: "1.jpg"; anchors.centerIn: parent}
    back: Image{source: "2.jpg"; anchors.centerIn: parent}
    transform: Rotation
    {
        id: rotation
        origin.x: flipable.width / 2
        origin.y: flipable.height / 2
        axis.x: 0; axis.y: 1; axis.z: 0
        angle: 0
    }
    states: State
    {
        name: "back"
        PropertyChanges { target: rotation; angle: 180 } //翻转效果
        when: flipable.flipped
    }
    transitions: Transition
    {
        NumberAnimation {target: rotation; property: "angle"; duration: 800}
    }
    MouseArea
    {
        anchors.fill: parent
        onClicked: flipable.flipped = !flipable.flipped
    }
}

 

三、状态

    State               定义一个配置对象和属性的集合

    PropertyChanges     使用一个State描述属性的改变

    StateGroup          包含一个状态集合和状态变换

    ParentChange        重新定义父集,也就是换个父节点

    AnchorChanges       在一个状态中改变anchors

1State

import QtQuick 2.0
 
Rectangle
{
    id: rect
    width: 100; height: 100
    color: "black"
    MouseArea
    {
        id: mouseArea
        anchors.fill: parent
        onClicked: rect.state == 'clicked' ? rect.state = "" : rect.state = 'clicked';
    }
    // 设置状态
    states:
    [
        State
        {
            name: "clicked"
            PropertyChanges { target: rect; color: "red" }
        }
    ]
}

2PropertyChanges

import QtQuick 2.0
 
Text
{
    id: myText
    width: 100; height: 100
    text: "Hello"
    color: "blue"
    states: State
    {
        name: "myState"
        PropertyChanges
        {
            target: myText
            text: "Goodbye"
            color: "red"
        }
    }
    MouseArea
    {
        anchors.fill: parent;
        onClicked: myText.state = 'myState'
    }
}

3ParentChange

    把指定的item换一个item父节点

import QtQuick 2.0
 
Item
{
    width: 200; height: 100
    Rectangle
    {
        id: redRect
        width: 100; height: 100
        color: "red"
    }
    Rectangle
    {
        id: blueRect
        x: redRect.width
        width: 50; height: 50
        color: "blue"
        states: State
        {
            name: "reparented"
            // 改变父节点
            ParentChange
            {
                target: blueRect;
                parent: redRect;
                x: 10; y: 10
            }
        }
        MouseArea
        {
            anchors.fill: parent;
            onClicked: blueRect.state = "reparented"
        }
    }
}

4AnchorChanges

import QtQuick 2.0
 
Rectangle
{
    id: window
    width: 120; height: 120
    color: "black"
    Rectangle
    {
        id: myRect;
        width: 50;
        height: 50;
        color: "red"
    }
    states: State
    {
        name: "reanchored"
        AnchorChanges
        {
            target: myRect
            anchors.top: window.top
            anchors.bottom: window.bottom
        }
        PropertyChanges
        {
            target: myRect
            anchors.topMargin: 10
            anchors.bottomMargin: 10
        }
    }
    // 鼠标事件
    MouseArea
    {
        anchors.fill: parent;
        onClicked: window.state = "reanchored"
    }
}

四、动画和变换

Behavior             默认的属性变换动画

SequentialAnimation  对定义的动画串行播放

ParallelAnimation    对定义的动画并行播放

PropertyAnimation    属性变换动画

NumberAnimation      对实数类型属性进行的动画

Vector3dAnimation    对QVector3d进行的属性

ColorAnimation       颜色进行的变换动画

RotationAnimation    对旋转进行的变换动画

ParentAnimation      对父节点进行变换的动画,改变绑定的父节点

AnchorAnimation      对anchor 进行改变的动画

PauseAnimation       延迟处理

SmoothedAnimation    允许属性平滑的过度

SpringAnimation      一种加速的效果

PropertyAction     允许在动画过程中对属性的直接改变

ScriptAction     允许动画过程中调用脚本

Transition     在状态变换中加入动作变化

1、Behavior

    一个特定的属性值改变时要应用一个动画,可以使用一个Behavior为一个属性改变指定一个默认的动画

import QtQuick 2.0
 
Rectangle
{
    id: rect
    width: 100; height: 100
    color: "red"
    // 针对宽度的动画
    Behavior on width
    {
        NumberAnimation { duration: 1000 }
    }
 
    MouseArea
    {
        anchors.fill: parent
        onClicked: rect.width = 50
    }
}

2、SequentialAnimation

    串行播放多个动画

Rectangle
{
    id: rect1
    width: 500; height: 500
    Rectangle
    {
        id: rect;
        color: "red"
        width: 100; height: 100
        // 串行播放多个动画,先横向移动,在纵向移动
        SequentialAnimation
        {
            running: true;
            NumberAnimation {target:rect; properties:"x"; to: 50; duration: 1000 }
            NumberAnimation {target:rect; properties:"y"; to: 50; duration: 1000 }
        }
    }
}

 

3ParallelAnimation

import QtQuick 2.0
 
Rectangle
{
    id: rect1
    width: 500; height: 500
    Rectangle
    {
        id: rect;
        color: "red"
        width: 100; height: 100
        // 并行播放动画,同时横向和纵向移动
        ParallelAnimation
        {
            running: true;
            NumberAnimation {target:rect; properties:"x"; to: 50; duration: 1000 }
            NumberAnimation {target:rect; properties:"y"; to: 50; duration: 1000 }
        }
    }
}

4、PropertyAnimation

    一个动画被应用为属性值源(property value source)

import QtQuick 2.0
 
Rectangle
{
    id: rect
    width: 100; height: 100
    color: "red"
    states: State
    {
        name: "moved"
        PropertyChanges
        {
            target: rect; x: 50
        }
    }
    transitions: Transition
    {
        // 属性动画 当属性 x或y发生变化的时候,就播放这样一个动画
        PropertyAnimation { properties: "x,y"; easing.type: Easing.InOutQuad }
    }
    MouseArea
    {
        anchors.fill: parent;
        onClicked: rect.state = "moved";
    }
}

5NumberAnimation

import QtQuick 2.0
 
Rectangle
{
    width: 100; height: 100
    color: "red"
    // 对当前item的x进行移动,目标移动到x = 50
    NumberAnimation on x { to: 50; duration: 1000 }
}

6ColorAnimation

颜色过度

import QtQuick 2.0
 
Rectangle
{
    width: 100; height: 100
    color: "red"
    ColorAnimation on color { to: "yellow"; duration: 1000 }
}

7RotationAnimation

import QtQuick 2.0
 
Item
{
    width: 300; height: 300
    Rectangle
    {
        id: rect
        width: 150; height: 100; anchors.centerIn: parent
        color: "red"
        smooth: true
        states: State
        {
            name: "rotated";
            PropertyChanges { target: rect; rotation: 180}
        }
        transitions: Transition
        {
            RotationAnimation
            {
                duration: 1000
                direction: RotationAnimation.Counterclockwise
            }
        }
    }
    MouseArea
    {
        anchors.fill: parent;
        onClicked: rect.state = "rotated"
    }
}

 

8ParentAnimation

    一个切换父节点的动画,平滑的过度

import QtQuick 2.0
 
Item
{
    width: 200; height: 100
    Rectangle
    {
        id: redRect
        width: 100; height: 100
        color: "red"
    }
 
    Rectangle
    {
        id: blueRect
        x: redRect.width
        width: 50; height: 50
        color: "blue"
        states: State
        {
            name: "reparented"
            ParentChange
            {
                target: blueRect
                parent: redRect
                x: 10; y: 10
            }
        }
        transitions: Transition
        {
            ParentAnimation
            {
                NumberAnimation { properties: "x,y"; duration: 1000 }
            }
        }
        MouseArea
        {
            anchors.fill: parent
            onClicked: blueRect.state = "reparented"
        }
    }
}

 

9AnchorAnimation

import QtQuick 2.0
 
Item
{
    id: container
    width: 200; height: 200
    Rectangle
    {
        id: myRect
        width: 100; height: 100
        color: "red"
    }
    states: State
    {
        name: "reanchored"
        AnchorChanges { target: myRect; anchors.right: container.right }
    }
    transitions: Transition
    {
        AnchorAnimation { duration: 1000 }
    }
    // 当控件加载完成后
    Component.onCompleted: container.state = "reanchored"
}

10PauseAnimation

    延迟效果

import QtQuick 2.0
 
Item
{
    id: container
    width: 200; height: 200
    Rectangle
    {
        id: myRect
        width: 100; height: 100
        color: "red"
        SequentialAnimation
        {
            running: true;
            NumberAnimation {target: myRect;to: 50; duration: 1000; properties: "x"; }
            PauseAnimation { duration: 5000 } // 延迟100毫秒
            NumberAnimation {target: myRect; to: 50; duration: 1000; properties: "y"; }
        }
    }
}

11SmoothedAnimation

    平滑过度

import QtQuick 2.0
 
Rectangle
{
    width: 800; height: 600
    color: "blue"
    Rectangle
    {
        width: 60; height: 60
        x: rect1.x - 5; y: rect1.y - 5
        color: "green"
        Behavior on x { SmoothedAnimation { velocity: 200 } }
        Behavior on y { SmoothedAnimation { velocity: 200 } }
    }
    Rectangle
    {
        id: rect1
        width: 50; height: 50
        color: "red"
    }
    focus: true
    Keys.onRightPressed: rect1.x = rect1.x + 100
    Keys.onLeftPressed: rect1.x = rect1.x - 100
    Keys.onUpPressed: rect1.y = rect1.y - 100
    Keys.onDownPressed: rect1.y = rect1.y + 100
}

 

12SpringAnimation

    平滑的过度过程,在动画结束的时候有种弹性的效果

import QtQuick 2.0
 
Item
{
    width: 300; height: 300
    Rectangle
    {
        id: rect
        width: 50; height: 50
        color: "red"
        Behavior on x { SpringAnimation { spring: 2; damping: 0.2 } }
        Behavior on y { SpringAnimation { spring: 2; damping: 0.2 } }
    }
    MouseArea
    {
        anchors.fill: parent
        onClicked:
        {
            rect.x = mouse.x - rect.width/2
            rect.y = mouse.y - rect.height/2
        }
    }
}

13PropertyAction

    主要是在动画过程中直接的改变一个属性

import QtQuick 2.0
 
transitions:Transition
{
    ...
    PropertyAction { target: theImage; property: "smooth"; value: true }
    ...
}

14ScriptAction

import QtQuick 2.0
 
SequentialAnimation
{
    NumberAnimation { ... }
    ScriptAction { script: doSomething(); }
    NumberAnimation { ... }
}

15Transition

import QtQuick 2.0
 
Rectangle
{
    id: rect
    width: 100; height: 100
    color: "red"
    MouseArea
    {
        id: mouseArea
        anchors.fill: parent
    }
    states: State
    {
        name: "moved"; when: mouseArea.pressed
        PropertyChanges { target: rect; x: 50; y: 50 }
    }
    transitions: Transition
    {
        NumberAnimation { properties: "x,y"; easing.type: Easing.InOutQuad }
    }
}

 

五、数据项

Binding         在创建的时候绑定一些数据到一些属性

ListModel       定义链表数据

ListElement     定义ListModel的一个数据项

VisualItemModel  包含可视化项(visual items)到一个view中,相当是一个容器

VisualDataModel  包含一个model和一个delegate,model包含需要的数据,delegate设计显示的项的信息

Package          把VisualDataModel共享给多个view

XmlListModel     特殊的一个模式使用XPath表达式,使用xml来设置元素

XmlRole          XmlListModel的一个特殊的角色

1、Binding

import QtQuick 2.0
 
Item
{
    width: 300; height: 300
    Text {id: app; text: "xxxfa"}
    TextEdit
    { id: myTextField;
        text: "Please type here..."
    }
    // 把myTextField和app的enteredText属性进行绑定
    Binding
    {
        target: app;
        property: "enteredText";
        value: myTextField.text
    }
}

 

 

2ListModel

import QtQuick 2.0
 
Rectangle
{
    width: 200; height: 200
    ListModel
    {
        id: fruitModel
        ListElement
        {
            name: "Apple"
            cost: 2.45
        }
        ListElement
        {
            name: "Orange"
            cost: 3.25
        }
        ListElement
        {
            name: "Banana"
            cost: 1.95
        }
    }
    Component
    {
        id: fruitDelegate
        Row
        {
            spacing: 10
            Text { text: name }
            Text { text: '$' + cost }
        }
    }
    ListView
    {
        anchors.fill: parent
        model: fruitModel
        delegate: fruitDelegate
    }
}

 

 

3、VisualItemModel

import QtQuick 2.0
 
Rectangle
{
    width: 100; height: 100;
    VisualItemModel
    {
        id: itemModel
        Rectangle { height: 30; width: 80; color: "red" }
        Rectangle { height: 30; width: 80; color: "green" }
        Rectangle { height: 30; width: 80; color: "blue" }
    }
    ListView
    {
        anchors.fill: parent
        model: itemModel
    }
}

 

4VisualDataModel

import QtQuick 2.0
 
Rectangle
{
    width: 200; height: 100
    VisualDataModel
    {
        id: visualModel
        model: ListModel
        {
            ListElement { name: "Apple" }
            ListElement { name: "Orange" }
        }
        delegate: Rectangle
        {
            height: 25
            width: 100
            Text { text: "Name: " + name}
        }
    }
    ListView
    {
        anchors.fill: parent
        model: visualModel
    }
}

 

六、视图

ListView      提供一个链表显示模型试图

GridView      提供一个网格显示模型试图

PathView      提供一个内容沿着路径来显示的模型

Path          定义一个PathView使用的轨迹

PathLine      定义一个线性的轨迹

PathQuad      定义一个二次贝塞尔曲线的轨迹

PathCubic     定义一个三次贝塞尔曲线的轨迹

PathAttribute 允许绑定一个属性上,具体看例子

PathPercent   修改item分配的轨迹 不是很明了其中的意思

WebView       允许添加网页内容到一个canvas上

1、GridView

import QtQuick 2.0
 
Rectangle
{
    width: 200; height: 400;
    ListModel
    {
        id: fruitModel
        ListElement
        {
            name: "Apple"
            cost: 2.45
        }
 
        ListElement
        {
            name: "Orange"
            cost: 3.25
        }
 
        ListElement
        {
            name: "Banana"
            cost: 1.95
        }
    }
 
    GridView
    {
        anchors.fill: parent
        model: fruitModel
        delegate: Column
        {
            Text {text:"name" + name}
            Text {text:"cost"+ cost}
        }
    }
}

 

2PathView

import QtQuick 2.0
 
Rectangle
{
    width: 200; height: 400;
    ListModel
    {
        id: fruitModel
        ListElement
        {
            name: "Apple"
            cost: 2.45
        }
 
        ListElement
        {
            name: "Orange"
            cost: 3.25
        }
 
        ListElement
        {
            name: "Banana"
            cost: 1.95
        }
    }
    PathView
    {
        anchors.fill: parent
        model: fruitModel
        delegate: Column
        {
            Text {text:"name" + name}
            Text {text:"cost"+ cost}
        }
 
        path:Path
        {
            startX: 120; startY: 100
            PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
            PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
        }
    }
}

 

3PathLine

import QtQuick 2.0
 
Rectangle
{
    width: 200; height: 400;
    ListModel
    {
        id: fruitModel
        ListElement
        {
            name: "Apple"
            cost: 2.45
        }
        ListElement
        {
            name: "Orange"
            cost: 3.25
        }
        ListElement
        {
            name: "Banana"
            cost: 1.95
        }
    }
    PathView
    {
        anchors.fill: parent
        model: fruitModel
        delegate: Column
        {
            Text {text:"name" + name}
            Text {text:"cost"+ cost}
        }
        path:Path
        {
            startX: 150; startY: 120
            PathLine { x: 200; y: 80; }
            PathLine { x: 100; y: 80; }
            PathLine { x: 150; y: 120; }
         }
    }
}

 

4PathAttribute

import QtQuick 2.0
 
Rectangle
{
    width: 200; height: 400;
    ListModel
    {
        id: fruitModel
        ListElement
        {
            name: "Apple"
            cost: 2.45
        }
        ListElement
        {
            name: "Orange"
            cost: 3.25
        }
        ListElement
        {
            name: "Banana"
            cost: 1.95
        }
    }
    PathView
    {
        anchors.fill: parent
        model: fruitModel
        delegate:
        Item
        {
            id: delitem;
            width: 80; height: 80;
            Column
            {
                Rectangle
                {
                    width: 40; height: 40;
                    scale: delitem.scale;
                    color: "red"
                }
                Text {text:"name" + name}
                Text {text:"cost"+ cost}
            }
        }
        path: Path
        {
            startX: 120; startY: 100
            PathAttribute { name: "Scale"; value: 1.0 }
            PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
            PathAttribute { name: "Scale"; value: 0.3 }
            PathQuad { x: 120; y: 100; controlX: -20; controlY: 75 }
        }
    }
}

5WebView

import QtQuick 2.0
import QtWebKit 1.0
 
WebView
{
    url: "http://www.nokia.com"
    preferredWidth: 490
    preferredHeight: 400
    scale: 0.5
    smooth: false
}


七、定位器

Column     整理它的子列(纵)

Row        整理它的子行(横)

Grid   设置它的子到一个网格上

Flow   目的是不让他的子项重叠在一起

    QML提供的多种用于定位的元素叫做定位器,包含在 QtQuick模块。QML定位器主要有Row、Column、Grid和Flow等。

1Column

    Column将子元素按照加入的顺序从上到下,在同一列排列出来。spacing属性用于定义子元素之间的间隔

Main.qml文件:

import QtQuick 2.0
 
Rectangle
{
    id: root
    width: 120
    height: 120
    color: "blue"
    Column
    {
        id: row
        anchors.centerIn: parent
        spacing: 8
        Button
        {
            color:"red"
            width:60
            text:"hello"
        }
        Button
        {
            color:"green"
            width: 96
            text:"close"
        }
        Button
        {
            color:"gray"
            width:60
        }
    }
}


wKiom1hVTWiSBxOCAAAKy6U-_fY111.png

2Row

    Row将其子组件放置在一行的位置,既可以设置从左向右,也可以设置从右向左,取决于layoutDirection属性。spacing属性用于指定子组件之间的间隔

Main.qml文件:

import QtQuick 2.0
 
Rectangle
{
    id: root
    width: 240
    height: 80
    color: "blue"
    Row
    {
        id: row
        anchors.centerIn: parent
        spacing: 8
        Button
        {
            color:"red"
            width:60
            text:"hello"
        }
        Button
        {
            color:"green"
            width: 96
            text:"close"
        }
        Button
        {
            color:"gray"
            width:60
        }
    }
}

wKioL1hVTYqT2nHYAAAfrJtf07M237.png

3Grid

    Grid元素将其子元素排列为一个网格,需要制定rows和columns属性,也就是行和列的数值。如果二者有一个不显式设置,则另外一个会根据子元素的数目计算出来。如果设置为3行,一共放入6个元素,列数会自动计算为2。flow和layoutDirection属性则用来控制添加到网格的元素的顺序。Grid元素也有spacing属性。

Main.qml文件:

import QtQuick 2.0
 
Rectangle
{
    id: root
    width: 200
    height: 200
    color: "black"
    Grid
    {
        id: grid
        rows:2
        anchors.centerIn: parent
        spacing: 8
        Button
        {
            color:"red"
            width:60
            text:"hello"
        }
        Button
        {
            color:"green"
            width: 96
            text:"close"
        }
        Button
        {
            color:"gray"
            width:60
        }
    }
}

wKiom1hVTa-QQLJFAAAQSZeT7BE610.png

    设定Grid的rows属性为2,添加3个子元素,columns属性会自动计算为2

4Flow

    Flow定位器会将其子元素以流的形式显示出来。使用flow和layoutDirection两个属性来控制显示方式,可以从左向右横向布局,也可以从上向下纵向布局。添加到Flow里面的元素,当Flow的宽度或高度不足时,元素会自动换行。为了令Flow正确工作,需要指定其宽度或者高度。

Main.qml文件:

import QtQuick 2.0
 
Rectangle
{
    id: root
    width: 200
    height: 200
    color: "black"
    Flow
    {
        anchors.fill: parent
        anchors.margins: 20
        spacing: 8
        Button
        {
            color:"red"
            width:60
            text:"hello"
        }
        Button
        {
            color:"green"
            width: 80
            text:"close"
        }
        Button
        {
            color:"gray"
            width:60
        }
    }
}

    三个按钮组件边长分别是60,80,60px,整个主窗口的宽是200px,Flow元素外边距 20px,因此Flow的宽度其实是 200px – 20px – 20px = 160px。Flow子元素间距为20px,两个按钮组件所占据的宽度就已经60px + 20px + 80px = 160px,3个则是160px + 20px + 60px = 240px > 200px,默认窗口大小一行只能显示两个按钮组件,第三个按钮组件自动换行。当拖动改变窗口大小时,可以观察Flow元素是如何工作的。如果拖动窗口宽度变长时,第三个按钮组件将会显示在第一行,如果拖动拖动窗口宽度变窄时,第二、三个按钮组件会换行到第二行、第三行。

5Repeater

    Repeater是一个结合定位器一起使用的元素。Repeater像一个for循环,能够遍历数据模型中的元素。

import QtQuick 2.0
 
Rectangle
{
    id: root
    width: 268
    height: 268
    color: "black"
    property variant colorArray: ["#00bde3", "#67c111", "#ea7025", "#ff0000"]
 
    Grid
    {
        anchors.fill: parent
        anchors.margins: 8
        spacing: 4
        Repeater
        {
            model: 16
            Rectangle
            {
                width: 60; height: 60
                property int colorIndex: Math.floor(Math.random()*4)
                color: root.colorArray[colorIndex]
                border.color: Qt.lighter(color)
                Text
                {
                    anchors.centerIn: parent
                    color: "black"
                    text: "Cell " + index
                }
            }
        }
    }
}

wKioL1hVTebD761pAAAkQKUwOJM102.png

    将Repeater同Grid一起使用,Repeater作为Grid的数据提供者。Repeater的model可以是任何能够接受的数据模型,并且只能重复基于Item的组件。重复生成16个定义的Rectangle元素。

    Repeater会按照model属性定义的个数循环生成其子元素。每一次循环,Repeater都会创建一个矩形作为自己的子元素。新生成的矩形的颜色按照Math.floor(Math.random()*3)的算法计算而得。颜色选择算法会得到 0,1,24四者之一,用于选择数组colorArray中预定义的颜色。JavaScript是QtQuick 的核心部分,JavaScript标准函数都是可用的。

    Repeater会为每一个子元素注入一个index属性,就是当前的循环索引,可以在子元素定义中直接使用index属性。

    使用Repeater时,需要注意性能问题。处理很大的数据模型,或者需要动态获取数据时,Repeater代码会非常吃力,需要另外的实现。Repeater不适用于处理大量数据或者动态数据,仅适用于少量的静态数据的呈现。

 

八、实用项

Connections        明确连接信号和信号句柄

Component          封装QML items 想一个组件一样

Timer              提供时间触发器

QtObject           基本的元素只包含objectName属性

Qt                 qml全局Qt object提供使用的枚举和函数

WorkerScript       允许在QML使用线程

Loader             控制载入item或组件

Repeater           使用一个模型创建多个组件

SystemPalette      为Qt palettes提供一个通道

FontLoader         载入字体根据名字或URL

LayoutItem         允许声明UI元素插入到qtGraphicsView 布局中

1Connections

import QtQuick 2.0
 
Rectangle
{
    width: 100; height: 100;
    MouseArea
    {
        id: area
        anchors.fill: parent;
    }
    Connections
    {
        target: area
        onClicked: { console.log(" ok");}
    }
}

2Component

import QtQuick 2.0
 
Item
{
    width: 100; height: 100
    Component
    {
        id: redSquare
        Rectangle
        {
            color: "red"
            width: 10
            height: 10
        }
    }
    // 动态的载入一个组件
    Loader { sourceComponent: redSquare }
    Loader { sourceComponent: redSquare; x: 20 }
}

3Timer

import QtQuick 2.0
 
Item
{
    width: 200; height: 40;
    Timer
    {
        interval: 500; running: true; repeat: true
        onTriggered: time.text = Date().toString() // 使用javascript获取系统时间
    }
    Text { id: time }
}

4Repeater

import QtQuick 2.0
 
Row
{
    Repeater
    {
        model: 3
        Rectangle
        {
            width: 100; height: 40
            border.width: 1
            color: "yellow"
        }
    }
}

5SystemPalette

Rectangle
{
    SystemPalette
    {
        id: myPalette;
        colorGroup: SystemPalette.Active
    }
    width: 640; height: 480
    color: myPalette.window
    Text
    {
        anchors.fill: parent
        text: "Hello!"; color: myPalette.windowText
    }
}

 

6FontLoader

Column 
{
    FontLoader { id: fixedFont; name: "Courier" }
    FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
    Text { text: "Fixed-size font"; font.family: fixedFont.name }
    Text { text: "Fancy font"; font.family: webFont.name }
}

 

九、变换

Scale       分派item 缩放行为

Rotation    分派item 旋转行为

Translate   分派item 移动行为

1Scale

import QtQuick 2.0
 
Rectangle
{
    width: 100; height: 100
    color: "blue"
    Rectangle
    {
        x: 50; y: 50;
        width: 20; height: 20;
        color: "red"
        transform: Scale { origin.x: 10; origin.y: 10; xScale: 3}
    }
}

 

2Rotation

import QtQuick 2.0
 
Rectangle
{
    width: 100; height: 100
    color: "blue"
    // 绕位置25,25 旋转45度
    transform: Rotation { origin.x: 25; origin.y: 25; angle: 45}
}

3Translate

import QtQuick 2.0
 
Row
{
    Rectangle
    {
        width: 100; height: 100
        color: "blue"
        // 沿y轴正方向移动20个像素
        transform: Translate { y: 20 }
    }
    Rectangle
    {
        width: 100; height: 100
        color: "red"
        // 沿y轴负方向移动20个像素
        transform: Translate { y: -20 }
    }
}

 

十、元素布局

    除了定位器,QML 还提供了另外一种用于布局的机制:锚点(anchor)。锚点允许我们灵活地设置两个元素的相对位置,使两个元素之间形成一种类似于锚的关系,也就是两个元素之间形成一个固定点。锚点的行为类似于一种链接,它要比单纯地计算坐标改变更强。锚点描述的是相对位置,在使用锚点时,必须指定两个元素,声明其中一个元素相对于另外一个元素。锚点是Item元素的基本属性之一,因而适用于所有QML可视元素。

    一个元素有6个主要的锚点的定位线top、bottom、left、right、horizontalCenter和verticalCenter。对于Text元素,还有一个baseline锚点。每一个锚点定位线都可以结合一个偏移的数值。top、bottom、left和right称为外边框;horizontalCenter、verticalCenter和baseline称为偏移量。

wKiom1hVTiGx59G1AAAaI-U2e6o087.png

import QtQuick 2.0
 
Rectangle {
    width: 200
    height: 200
    color: "blue"
    border.color: Qt.lighter(color)
 
    MouseArea
    {
        anchors.fill: parent
        drag.target: parent
    }
}

wKiom1hVTkOQsgLwAAAQR9hIFJU496.png

    MouseArea组件是一个用于处理鼠标事件的组件。drag.target: parent说明拖动目标是parent,拖动对象是MouseArea的父组件,Rectangle组件。anchors.fill设置内部蓝色矩形的锚点为填充(fill),填充的目的对象是parent;anchors.margins: 10表示填充边距是10px。虽然设置了矩形宽度为12px,但锚点的优先级要高于宽度属性设置,所以蓝色矩形的实际宽度是100px – 10px – 10px = 80px。

import QtQuick 2.0
 
Rectangle
{
    id: root
    width: 220
    height: 220
    color: "black"
 
    Rectangle
    {
        x: 10
        y: 10
        width: 100
        height: 100
        color:"blue"
        Rectangle
        {
            x:8
            y: 8
            width:60
            height:60
            color:"green"
            anchors.left: parent.left
            anchors.leftMargin: 8
            MouseArea
            {
                anchors.fill: parent
                drag.target: parent
            }
        }
    }
}

wKioL1hVTmmDzE8vAAATCDcpzXE109.png

    anchors.left设置内部绿色矩形的锚点为父组件的左边线(parent.left);左边距是8px。可以试着拖动绿色矩形,拖动绿色矩形时,绿色矩形只能沿着距离父组件蓝色矩形左边8px的位置上下移动。

    anchors.left: parent.right设置锚点的左侧为父组件的右侧

    anchors.top: parent.bottom设置锚点的上侧为父组件的底侧

    anchors.topMargin: 4设置锚点的上侧边距为4

    anchors.horizontalCenter: parent.horizontalCenter设置锚点的水平中心为父组件的水平中心