【零基础学QT】【045】Qml基本用法

本篇博客通过一个详细的UI例子来逐个点介绍Qt Quick的基本用法,尽量通过简单例子来覆盖全部主要知识点,阅读时请对照代码来逐个理解各个知识点

Qt Quick基本用法

  • Demo使用技巧:由于以下代码集中了大量知识点,同时显示会特别混乱,大家只要通过visible: false隐藏无关元素即可
  • 注释:Qml和Javascript一样,通过双斜杠添加注释
  • 给元素设置id:每个节点都可以设置一个id属性,其它元素可能通过id关联这个节点,参照node01
  • 向DOM树中添加节点:参照node02
  • 导入类库:Window,Text等元素都来自Qt Quick类库,需要导入后才能使用,参照首行import语句
  • Qml基本类型:Qml提供了int,real,string,bool,list等类型,不需要导入任何类库就能使用
  • Qt Quick内置类型:Qt Quick提供了date,point,rect,size,基本控件等类型,导入Qt Quick模块即可使用
  • Javascript类型:Qml可以像Javascript一样,直接通过var来声明一个对象,它没有具体类名,但可以通过变量名直接访问,参照node03和node04,node03声明了一个innerObject对象,node04可以直接引用这个对象的值
  • 执行Javascript代码:在onCompleted,onClicked等方法内,可以执行Javascript代码,参照node04
  • 属性引用:一个元素,可以直接使用其它元素的属性值,或拿来进行运算,这个功能非常强大,比如我们想要高为宽的一半时,只需写出【height: width * 0.5】即可
  • 通过锚布局定位元素:锚布局允许通过锚点,边距,填充,居中等方式组合来定位元素位置,参照node05
  • 设置元素点击区域:通过给元素添加MouseArea子节点,可以为元素添加点击事件,并且可以控制点击区域范围,参照node06
  • 设置字体:通过给Text元素添加font子节点,就可以设置Text的字体,当font的属性很简单只有一个的时候,也可以简写成【font.bold: true】这种格式,参照node07
  • 设置边框:边框的使用和字体同理,参照node08
  • 图片控件:通过Image元素可以显示图片,参照node09
  • 设置鼠标滑入滑出事件:给MouseArea设置onEntered,onExited事件方法即可,参照node10
  • 自定义组件:由于篇幅较长,稍后我们开一篇专门的博客来讲解
  • 编码规范:由于一个Qml文件中可能包含诸多内容,为了方便阅读,应当有一个书写规范,一般按照id,自定义属性,属性赋值,事件声明,状态声明,动画声明,自定义函数的顺序来编写
  • 定义动画:Qt内置了AnchorAnimation,ColorAnimation,NumberAnimation,PathAnimation,PropertyAnimation,RotationAnimation等常用动画,非常前面,如node11所示,是一个简单的颜色渐变动画
  • 定义复杂动画:上面介绍的是一个非常简单的动画,控件一创建便执行,实际大多情景比这个要复杂,动画改变的属性可能不止一个,动画往往需要指定在状态变化时执行,这时单纯的Animation已经不再能满足我们的需求,我们需要配合State和Transition来实现这些复杂动画,参照node12
  • 数组简写:在Qml中数组通过[ ]来表示,但是当数组只有一个元素时,也可以省略[ ]
  • 加载Javascript代码:Qml可以直接将Javascript加载为一个模块对象,直接进行使用,在这一点上,Qt Quick做得比原生Javascript更加先进,参照node13和import语句
  • 可视基类:所有的Qt Quick可视化元素,即控件节点,都继承自Item,参照node14,像x,y,z,width,height这些基本属性,都是继承自Item的
  • 控件堆叠顺序:当一个元素中包含多个子元素时,可以通过z值来控制元素的显示顺序,z值较大的将显示在上面,遮挡z值较小的元素,默认的z值为0,z值相同的情况下,排在布局靠后的元素显示在上层,参照node14
  • 坐标转换:同一个点相对于不同控件的坐标是不同的,比如对于一个Window-Item-Rectangle的三级Dom结构,点相对于Window,Item,Rectangle的坐标都是不一样的,除非这三级节点的左上角都是对齐的,要获取一个点相对于某个元素的坐标位置,可以参考node15
  • 界面布局:内容不难,但由于布局有很多种,还有新版旧版之分,篇幅较长,接着我们开一篇专门博客来讲解
  • 显示富文本:Text可以显示复杂带样式的文本,如加粗,倾斜,彩色,链接,序号等,通过【textFormat: Text.StyledText】或【textFormat: Text.RichText】即可启用对应的功能,StyledText仅支持基本的简单文本标签,RichText支持HTML4标签
  • 使用文本编辑框:TextInput是一个文本编辑控件,但是它没有任何默认样式,甚至连基本的边框都没有,需要用户自己定义,参照node16
  • 更多高级控件和属性:Qt每个控件都包含了诸多属性,每一个都可以写成一幅长篇博客,但是不管对于新手还是老手来说,这都不是一个明智之举,这里只讲解核心知识点和思路,以便大家可以快速上手进行Qt项目开发,具体细节可以用到时再探究,死背属性意义不大,以后换一种语言,换一种框架,可能又是新的属性和用法,没太大复用价值

Demo源码


	//main.qml
	
	import QtQuick 2.12
	import QtQuick.Window 2.12
	import "script/math.js" as MathScript
	
	//窗口节点
	Window {
	    id: node01
	    visible: true
	    width: 640
	    height: 480
	    title: "Qt Quick Demo"
	
	    //测试基本使用
	    Text {
	        id: node02
	        visible: false
	        text: "Node 02"
	    }
	
	    //测试Javascript对象
	    Text {
	        property var innerObject: ({
	                                       "title": "Node 04"
	                                   })
	
	        id: node03
	        visible: false
	        text: "Node 03"
	    }
	
	    //测试Javascript代码
	    Text {
	        id: node04
	        visible: false
	        text: node03.innerObject.title
	
	        Component.onCompleted: {
	            var jsObject = {
	                "id": 1,
	                "name": "Javascript Object"
	            }
	
	            console.log(node03.text)
	            console.log(node04.text)
	            console.log(jsObject.name)
	        }
	    }
	
	    //使用矩形区域测试锚布局
	    Rectangle {
	        id: node05
	        visible: false
	        width: 400
	        height: 400
	        radius: 5
	        color: "red"
	
	        anchors.left: parent.left
	        anchors.top: parent.top
	        anchors.leftMargin: 10
	        anchors.topMargin: 10
	    }
	
	    //测试点击区域
	    Rectangle {
	        id: node06
	        visible: false
	        width: 400
	        height: 400
	        color: "red"
	        anchors.centerIn: parent
	
	        //只能点击下半区域
	        MouseArea {
	            anchors.fill: parent
	            anchors.topMargin: parent.height * 0.5
	            onClicked: {
	                console.debug("Rectangle Clicked")
	            }
	        }
	    }
	
	    //测试字体
	    Text {
	        id: node07
	        visible: false
	        text: "Node 07"
	
	        font {
	            pointSize: 30
	            bold: true
	            italic: true
	        }
	    }
	
	    //测试边框
	    Rectangle {
	        id: node08
	        visible: false
	        width: 200
	        height: 200
	        color: "yellow"
	
	        border {
	            color: "red"
	            width: 2
	        }
	    }
	
	    //测试图片
	    Image {
	        id: node09
	        visible: false
	        source: "images/1.png"
	        width: parent.width
	        height: parent.height
	        fillMode: Image.Stretch
	    }
	
	    //测试鼠标悬浮事件
	    Rectangle {
	        id: node10
	        visible: false
	        width: 200
	        height: width
	        color: "yellow"
	        radius: 100
	        border.color: "red"
	        border.width: 2
	
	        MouseArea {
	            anchors.fill: parent
	            hoverEnabled: true
	            onEntered: {
	                parent.border.width = 4
	            }
	            onExited: {
	                parent.border.width = 2
	            }
	        }
	    }
	
	    //测试基本动画
	    Rectangle {
	        id: node11
	        visible: false
	        width: 200
	        height: width
	        radius: 100
	
	        //控件创建时,执行一个颜色渐变动画
	        ColorAnimation on color {
	            from: "yellow"
	            to: "orange"
	            duration: 3000
	        }
	    }
	
	    //测试复杂动画
	    Rectangle {
	        id: node12
	        visible: false
	        width: 200
	        height: width
	        radius: 100
	        state: "A"
	
	        //点击时切换到状态B
	        MouseArea {
	            anchors.fill: parent
	            onClicked: {
	                node12.state = "B"
	            }
	        }
	
	        //声明两种状态,指定状态值
	        states: [
	            State {
	                name: "A"
	                PropertyChanges {
	                    target: node12
	                    color: "yellow"
	                }
	                PropertyChanges {
	                    target: node12.border
	                    width: 2
	                    color: "green"
	                }
	            },
	            State {
	                name: "B"
	                PropertyChanges {
	                    target: node12
	                    color: "orange"
	                }
	                PropertyChanges {
	                    target: node12.border
	                    width: 5
	                    color: "blue"
	                }
	            }
	        ]
	
	        //定义从A状态切换到B状态时的动画
	        transitions: Transition {
	            from: "A"
	            to: "B"
	            ColorAnimation {
	                target: node12
	                duration: 3000
	            }
	            NumberAnimation {
	                target: node12.border
	                property: "width"
	                duration: 3000
	            }
	        }
	    }
	
	    //测试加载Javascript文件
	    Rectangle {
	        id: node13
	        visible: false
	        width: 200
	        height: width
	        radius: 100
	        color: "yellow"
	
	        Component.onCompleted: {
	            console.debug("MathScript", MathScript.sum(1, 1))
	        }
	    }
	
	    //测试Item
	    Item {
	        id: node14
	        visible: false
	        anchors.fill: parent
	
	        Rectangle {
	            width: 100
	            height: 100
	            x: 100
	            y: 100
	            z: 1
	            color: "red"
	        }
	
	        Rectangle {
	            width: 100
	            height: 100
	            x: 150
	            y: 150
	            z: -1
	            color: "lightblue"
	        }
	    }
	
	    //获取控件坐标
	    Rectangle {
	        id: node15
	        visible: false
	        anchors.fill: parent
	        color: "yellow"
	
	        Rectangle {
	            id: node15Rect
	            width: 100
	            height: 100
	            color: "red"
	            anchors.top: parent.top
	            anchors.left: parent.left
	            anchors.topMargin: 10
	            anchors.leftMargin: 10
	
	            Component.onCompleted: {
	                //将node15Rect中的点,转化为在node15中的坐标
	                console.debug(node15.mapFromItem(node15Rect, 0, 0))
	                //将node15中的点,转化为在node15Rect中的坐标
	                console.debug(node15.mapToItem(node15Rect, 10, 10))
	                //同理,可将Item中的坐标与Window中的坐标进行转换
	                //由于Window不继承自Item,需要通过Window.contentItem来获得根节点
	                console.debug(node01.contentItem.mapFromItem(node15Rect, 0, 0))
	                console.debug(node01.contentItem.mapToItem(node15Rect, 10, 10))
	            }
	        }
	    }
	
	    //测试文本编辑框
	    Rectangle {
	        id: node16
	        visible: true
	        anchors.fill: parent
	        anchors.margins: 100
	        color: "yellow"
	
	        TextInput {
	            id: node16Input
	            anchors.fill: parent
	            text: "Hello World"
	            color: "red"
	            font.pointSize: 50
	            focus: true
	            clip: true //文本裁剪,可以防止文本超出parent显示
	        }
	    }
	    
	}


	//math.js

	function sum (a, b) {
	    return a + b;
	}

发布了442 篇原创文章 · 获赞 45 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/u013718730/article/details/104112151