美文网首页首页投稿(暂停使用,暂停投稿)程序员
Qt Quick 学习笔记(一) QML界面模型

Qt Quick 学习笔记(一) QML界面模型

作者: 3f9b7dcb0845 | 来源:发表于2017-06-23 15:00 被阅读1924次

基本语法

QML是类似于HTML的标记型语言,有与HTML类似的树形节点结构,同时又包含类似JS的函数语法。一个基础的QML文档类似这个样子

import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0

ApplicationWindow {
    objectName: "root"
    visible: true
    width: 1280
    height: 720
    maximumHeight: this.height
    minimumHeight: this.height
    maximumWidth: this.width
    minimumWidth: this.width
    title: qsTr("Security Check")
    font.family: "Source Han Sans CN Normal"

    Image{
        x: 0
        y: 0
        property int _test: 8
        property var list: []
    }
}

其中 <code>ApplicationWindow</code> 就是整个界面窗口的根节点,可以通过在C++文件中使用

QObject* rootObject;
rootObject = engine.rootObjects().first();

得到指向根节点的指针,便于信号槽的链接和函数的调用(后文

声明一个元素

在QML中,一个元素类似这样

Image{
    property a: x
    property b: y
}

每一种元素有预定义的属性,具体每个类型的元素有什么属性,可以参考All QML Types.


动态增加一个元素

在QML中,动态增加元素是基于一个模版(Component)的,所有需要动态添加的对象,都需要先存在一个模版元素中。
例如动态添加一个Image元素,可以这样构建:

    Component{
        id:create
        Image {
            id: tourist
            source: sprites[Math.floor((Math.random()*3))]
            width: 20
            height: 20
            property int x_axid: 1010
            property int y_axid: 120
            x:x_axid
            y:y_axid
            Behavior on x{
                SmoothedAnimation{ duration: 500 }
            }
            Behavior on y{
                SmoothedAnimation{ duration: 500 }
            }
        }

虽然整个QML文档中不允许同时有多个id相同的元素(类似HTML),但是给动态创建的内容id属性却是合法的。

当需要创建这个图形对象时,就可以调用 <code>create.createObject(parentNode)</code> 这个QML函数来在parentNode节点下创建一个Image元素,该函数返回创建的元素的指针。
需要重复创建多个相同的对象时,可以将创建的object存入一个列表中,便于管理,例如这样:

var obj = create.createObject(image,{});//从模版生成元素
list.push(obj)//将元素加入列表

绑定自定义属性

每个QML元素类型除了预定义的属性(例如x,y,opacity)以外,也可以添加一些我们自定义的属性。
给元素添加绑定属性类似这样:

Image{
    id: img
    x: 0
    y: 0
    property int maxNum: 15//绑定一个整形属性
    property var list: []//绑定一个列表
}

访问一个节点的属性类似这样

img.maxNum = 15//赋值操作

绑定属性有很多应用,例如在对象的动画中,为了避免对x,y值重复操作,可以使用绑定属性来避免冲突(后文)


使用数据模型

在QML中,有一些预制好的数据模型,例如 ListModel.
使用 ListModel, 可以随意创建基于 ListItem 的列表,每个元素是一个 ListItem,元素内部又可以包含许多属性,类似C 中的结构体数组
一个典型的 ListModel 类似这样:

ListModel {
                            id:cpStateList
                            ListElement {
                                cpIndex:0
                                cpState: "空闲"
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:1
                                cpState:  "空闲"
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:2
                                cpState:  "空闲"
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:3
                                cpState: "空闲"
                                cpCurrentTime:0
                                cpNeedTime:0
                            }
}

这样,当我们需要进行数据绑定时,可以将一个列表中的数据和 ListModel 中的 ListItem 一一绑定,当需要操作数据时,使用这样的方法:

var obj = cpStateList.get(Index)//得到在ListModel中编号为Index的元素
obj.xxx = ???//对xxx属性进行赋值

ListModel还有一个重要的应用,就是在一些预置的 View 中作为数据源,渲染到对应的模版上。
例如,一个 GridView 可以方便的构造一个网格视图,每一个网格都是一个基于delegate(代表性模版)的结构,结构中的数据会自动调用对应的 model 内部的数据。
一个典型的 GridView 类似这样:

GridView {

                        id: cpStateBoard
                        x: 56
                        y: 13
                        width: 894
                        height: 84
                        cellHeight: height
                        cellWidth: width/8

                        delegate: Item {
                            Column {
                                spacing: 30
                                    Text{
                                        x:0
                                        y:10
                                        text:cpState
                                        font.family: "Source Han Sans CN Normal"
                                    }

                                    Text {
                                        x: 0
                                        y: 30
                                        text: cpCurrentTime + '/' + cpNeedTime
                                        opacity: cpState == "关闭" ? 0 : 1
                                        font.family: "Source Han Sans CN Normal"
                                        //anchors.horizontalCenter: parent.horizontalCenter
                                    }
                                }
                            }
                        }
                        model: ListModel {
                            id:cpStateList
                            ListElement {
                                cpIndex:0
                                cpState: "空闲"
                                cpCurrentTime:0
                                cpNeedTime:0
                            }

                            ListElement {
                                cpIndex:1
                                cpState:  "空闲"
                                cpCurrentTime:0
                                cpNeedTime:0
                            }
}

当使用的model内部有两个数据时,就会渲染出两个网格有两个 Text元素,每个网格内部布局和delegate一致,分别使用了ListElement中的两个数据。通过对model的操作,一个网格就可以动态的增删并且保持统一的格式。


动画的使用

给一个元素添加动画主要有几种形式:

  • 在元素中定义一个完整的动画,需要运动时调用
  • 给某个属性绑定插值,当某个属性发生改变时自动进行补间

比较常用的是第二种。例如,我希望这个图像运动时能够平滑的移动,可以这样:

    Rectangle {
        id: details
        opacity: 0


        Behavior on opacity{
            NumberAnimation{
                duration: 200
            }
        }

        Behavior on x{
            SmoothedAnimation{
                duration: 100
            }
        }

        Behavior on y{
            SmoothedAnimation{
                duration: 100
            }
        }
    }

这样,当x、y值发生改变时,就自动进行一个 SmmoothedAnimation ,经历时长100ms
这个方法也可以绑定到opacity属性上,实现淡入淡出的效果。

需要注意的是,当一个元素在运动过程中,如果检查他的x,y属性,会发现是当前运动中的值,而不是最终值。所以一定避免在运动过程中进行类似<code> item.x -= 100 </code>这样的赋值,否则最终的位置将不是第一次赋值-100,而是运动到某个时刻的位置-100.
为了避免这样的情况,也可以使用绑定属性的方法,例如(注意x,y属性):

Image {
            id: tourist
            source: sprites[Math.floor((Math.random()*3))]
            width: 20
            height: 20
            property int x_axid: 1010
            property int y_axid: 120
            x:x_axid
            y:y_axid
            Behavior on x{
                SmoothedAnimation{ duration: 500 }
            }
            Behavior on y{
                SmoothedAnimation{ duration: 500 }
            }
        }

每次需要改变位置时,改变x_axid/y_axid的值,而x,y属性会随之改变,同时进行运动动画,但是运动过程中,进行<code> item.x_axid -= 100 </code>,改变的仍然是最终值-100.


QML进阶

最后我想说,QML和HTML类似之处太多,甚至当在QML中不懂怎么写时,试试用JavaScript的写法,说不定能用,例如QML中也有Math.floor()、Number()、String()等等一众函数,QML中的变量也是var(偶尔又是int,傻傻分不清),总之可以多借鉴。

相关文章

  • Qt Quick 学习笔记(一) QML界面模型

    基本语法 QML是类似于HTML的标记型语言,有与HTML类似的树形节点结构,同时又包含类似JS的函数语法。一个基...

  • QML用户界面基础(一)

    QML 允许开发人员以声明的方式构建用户界面。Qt Quick[https://doc.qt.io/qt-5/qt...

  • 小白学qml 1

    前言 作为小白,学习qml真的是非常的简单,快速。 Qt Quick是Qt5中⽤户界⾯技术的涵盖。 Qt Quic...

  • 说说QtQuick提供的类型

    Qt Quick 提供了标准qml类型,可视化类型,动画类型以及其他qml类型。 标准qml类型 官网的介绍原文请...

  • Qt应用程序快速开发指南(桌面版)- 1 -

    让我们以身作则学习!本指南的目的是使您熟悉使用Qt Quick的最佳编程实践用于使用QML构建应用程序。本指南的前...

  • QML Book 第四章 入门 1

    4. 出发 本章概述 Qt 5 中使用的声明式用户界面语言 QML。我们将讨论 QML 语法,这是一个元素树,其次...

  • QML 组件

    参考:QML Tutorial 2 - QML Components - Qt for Python[https:...

  • Qt/QML 插件系统

    Qt/QML 插件系统 本文将简要介绍一下 Qt 和 QML 的插件系统,并用几个简单的示例介绍 QML 的几种插...

  • QtQuick Canvas画图教程

    本指南的目标是向您介绍使用qt quick 2.0中的canvas类型的最佳编程实践。本指南的先决条件是对QML语...

  • Qt 动画应用

    Qt的动画机制,能用在QWidget、QGraphicWidget、以及在QML中也有部分应用的模型,这里只是先举...

网友评论

    本文标题:Qt Quick 学习笔记(一) QML界面模型

    本文链接:https://www.haomeiwen.com/subject/hjrccxtx.html