1 QML基础类型和组件
1.1 QtObject
- 派生类Item
- 所有可视项目的基类。定义了常用属性,比如位置、宽度、高度等
- 示例
-
Item{x:100; y:100; width:100;height:100}
-
- C++实现
-
#include <QQuickItem>
-
- 派生类
- Rectangle
- Text
- 示例
-
QtObject{id: attrubutesproperty string nameproperty int sizeproperty variant attributes}
- 不可显示只有一个
objectName
属性
-
- C++实现
-
#include <QObject>
-
1.2 Window
- 窗口组件,窗口中的所有组件都是
QtObject
- 示例
-
Window{x:100; y:100; width:100;height:100}
-
- C++实现
-
#include <QQuickWindow>
-
- 默认不打开
-
visible: true // 打开
-
- ApplicationWindow
- 包含了菜单栏、状态栏的窗口
1.3 Component
- 管理动态创建的对象时,必须确保创建上下文比创建的对象寿命更长
- 示例
-
var component = Qt.createComponent("Button.qml");if(component.status == Component.Ready){var button = component.createObject(container);button.color = "red";}
-
- Signals
- completed
- destruction
- C++实现
-
QQmlComponent // 继承于QObject
-
2 属性
2.1 属性分类
- 对象名称(id)
- 每个对象类型都有id属性,不能重新定义或覆盖
- 小写字母或下划线开头,不能包含除字母、数字和下划线以外的字符
- 可以理解为类的实例对象名
-
Window {id: root // 对象名称}
- attributes特性(类自带)
-
Window {id: root visible: truewidth: 640 // attributes特性height: 480 // attributes特性title: qsTr("Hello World")}
-
- property属性(自己定义)
[default][required][readonly] property <propertyType><propertyName>
- default表示默认属性(访问子节点的属性),required表示必填属性,readonly表示只读属性
-
Window {id: root // 对象名称visible: truewidth: 640 // attributes特性height: 480 // attributes特性title: qsTr("Hello World")// 自定义属性property int iIndex}
2.2 属性定义和赋值
[default] property <propertyType> <propertyName> : <value>
-
// 设置值property var name: "Jack"property int code: 10010property int doublecode: code * 2
2.3 属性访问
- 通过对象id访问
[<object>.]<propertyName> = value
- 访问父节点属性
parent.属性
-
Window {id: rootNodevisible: truewidth: 640height: 480title: qsTr("Hello World")property int countNum: 1000Button{id: testBtntext: "text property"onClicked: {// 通过对象id访问属性rootNode.countNum++print(rootNode.countNum)}}Item{id: subNodewidth: 300property int itemNum: 520Button{text: "test parent property"x: 50y: 50width: 150onClicked: {// 访问父节点属性print(parent.itemNum)}}}}
2.4 属性类型
- 概述
- 变量分为值类型和对象类型
- 值类型:按值传递
- 对象类型:通过引用传递
- 值类型
- QML语言内部值类型
int、bool、double、real(既可以是整型,也可以是浮点型)、date、list、string、var(不确定类型时使用)、void、url
var(JavaScript类型)
- QtQml module中值类型
point、rect、size
- QtQuick module中值类型
color、font、vector2d、vector3d、vector4d
-
Window {id: rootNodevisible: truewidth: 640height: 480title: qsTr("Hello World")property int countNum: 1000// QML语言内部值类型property bool bval: trueproperty real rval: 3.14property double dval: 3.1415property string svar: "string svar"property var vvar1: 1314property var vvar2: "string vvar"// QtQml module中值类型property point ipos: "100, 200"//QtQuick module中值类型property color mycolor: "red" // 或者 "#FF0000"}
- QML语言内部值类型
- 对象类型
- C++定义的值类型
- QML object type
-
Window {id: rootNodevisible: truewidth: 640height: 480Item{// 值类型property int nNum: 100// 对象类型property Button btnButton{text: "ItemBtn"x: 100y: 50width: 200onClicked: {// 给nNum赋值,不会改变width的值parent.nNum = widthparent.nNum += 10print("width: " + width)// 给btn赋值,会改变testBtn的值parent.btn = rootBtnparent.btn.text = "world"}}}Button{id: rootBtntext: "rootBtn"}}
-
- qml文件定义的类型
- 文件名即为类型,首字母要大写
- 枚举类型
- 枚举类型和值必须以大写字母开头
2.5 属性其他用法
- 属性别名
[default] property alias <name> : <alias reference>
- 不能包含任意JavaScript表达式,应用最多两层深度,仅当组件完全初始化后,别名才会被激活
-
Window {id: rootNodevisible: truewidth: 640height: 480Rectangle{x: 100width: 100height: 100Button{width: 100height: 100text: "test alias"// 定义别名property alias rootx: rootNode.xonClicked: {rootx += 5}}}}
3 函数
- 函数定义
function <functionName>([<parameterName>[:<parameterType>][,...]])[:<returnType>]{<body>}
- 必须小写字母开头,参数类型可选,返回值可选
- 函数调用
- 通过id访问
- 函数定义和调用实例
-
Window {id: rootNodevisible: truewidth: 640height: 480// 定义函数function testFunc(index: int, name: string):int{print("call testFunc: ", + index + ":" + name);return 1001}Button{text: "btn testFunc"onClicked: {// 调用函数var ret = rootNode.testFunc(1001, "Jack")print("ret: " + ret)ret = itemNode.testItem1("hello")print("ret: " + ret)}}Item{id: itemNode// 参数类型和返回值类型可以省略function testItem1(str){print("testItem1: " + str)return "testItem"}}}
-
- 变量中存放函数地址
- MyType.qml文件
-
Text {text: "test callback"// 属性变量存放函数地址property var myCb: function(){print("MyType myCb")}Button{x: 100text: "call myCb"onClicked: {myCb()}}}
- main.qml文件
-
Window {id: rootNodevisible: truewidth: 640height: 480MyType{y: 60// 重载myCb:function(){print("in main myCb")}}}
4 信号和槽
4.1 信号语法
signal <name>[([<type><parameter name>[, ...]])]
4.2 控制自带信号处理
-
Window {visible: truewidth: 640height: 480title: qsTr("Hello World")Rectangle{// 子窗口创建信号Component.onCompleted:{print("Rectangle Component.onCompleted")}// 子窗口销毁信号Component.onDestruction: {print("Rectangle Component.onDestruction")}}// 窗口创建信号 - 会先于 Rectangle 创建信号调用Component.onCompleted:{print("Component.onCompleted")}// 窗口销毁信号Component.onDestruction: {print("Component.onDestruction")}// 属性property Item myItem: Item{// 属性创建信号Component.onCompleted:{print("Item Component.onCompleted")}// 属性销毁信号Component.onDestruction: {print("Item Component.onDestruction")}}Button{text: "Btn"// 按钮点击信号onClicked: {print("Button onClicked")}// 按钮按下信号onPressed: {print("Button onPressed")}}}
4.3 自动绑定的信号和槽函数
- 接收信号通知,定义一个名为on函数,其中是信号的名称,第一个字母大写。
-
Window {id: rootNodevisible: truewidth: 640height: 480title: qsTr("Hello World")Button{text: "signal test"// 信号定义signal mySig1signal mySig2(int code, string name)onClicked: {// 发送信号mySig1()mySig2(1001, "Jack")}// 绑定信号槽onMySig1:{print("onMySig1")}onMySig2:(c, n)=> {print("onMySig2, code: " + c + ", name: " + n)}}}
4.4 属性更改信号处理程序
- 属性值更改时,可以在对应的
on<PropertyName>Change
中做相应逻辑处理 -
Window {id: rootNodevisible: truewidth: 640height: 480title: qsTr("Hello World")Rectangle{x: 100width: 100height: 100color: "blue"// 定义一个属性property real mysize: 1.0// 属性变化时,处理相应逻辑onMysizeChanged: {width = mysize * 100;height = mysize * 100;}Button{text: "change size"onClicked: {parent.mysize += 0.1}}}}
4.5 手动将信号连接到方法
-
Window {id: rootNodevisible: truewidth: 640height: 480title: qsTr("Hello World")// 手动连接信号槽Item{// 定义信号signal testConnSig// 定义槽函数function testConnSlot(){print("call testConnSlot")}Component.onCompleted: {// Item初始化// 手动绑定信号槽 - 可以绑定多次testConnSig.connect(testConnSlot)}Component.onDestruction: {// Item销毁// 解除绑定 - 解绑一次即可testConnSig.disconnect(testConnSlot)}Button{text: "test conn"onClicked: {// 发送信号parent.testConnSig()}}}}
5 多文件之间信号传递
- MyType.qml文件
-
Item {// 定义信号signal setBtnSize(int w, int h)Rectangle{width: 200height: 200color: "blue"Button{text: "test conn sig"onClicked: {print("onClicked conn sig")parent.width += 5parent.height += 5// 发送信号setBtnSize(parent.width, parent.height);}}}}
-
- main.qml文件
-
Window {id: rootNodevisible: truewidth: 640height: 480title: qsTr("Hello World")Item{Component.onCompleted: {// 绑定信号槽mytypeNode.setBtnSize.connect(rectNode.recvSetSize)}MyType{id: mytypeNodey: 250}Rectangle{id: rectNodewidth: 200height: 200color: "green"// 槽函数function recvSetSize(w, h){print("recvSetSize, w: " + w + "," + h);width = wheight = h}}}// 可以通过此方法直接处理信号,不用进行绑定Connections{target: mytypeNodefunction onSetBtnSize(w, h){print("onSetBtnSize, w: " + w + "," + h);}}}
-