一、属性通过 “属性:值” 语法来指定
二、每一个对象都可以指定一个唯一的id值
三、QML提供了一个QtQuick工具栏,在编写代码时按下"Ctrl + Alt + 空格"调出,也可以右键选择“显示QtQuick工具栏”
四、QML属性是类型安全的,它们只允许分配一个匹配该属性类型的值
五、QML基本类型
action | action类型拥有QAction的所有属性 |
bool | true和false |
color | 一个color就是一个标准的颜色名称加上双引号 |
date | 一个date被指定为“YYYY-MM_DD” |
double | |
enumeration | 枚举 |
font | QFont |
int | |
list | |
real | |
rect | 一个rect类型包含了x, y, width, height属性 |
size | 一个size类型包含了width, height属性 |
string | |
time | 一个time被指定为“hh:mm:ss” |
url | |
variant | |
vector3d | 一个vector3d类型包含了x, y, z属性 |
六、当一个属性更改值时,它会发送一个信号,使用"on<Property>Changed"语法
七、列表被包含在一对方括号中,使用逗号分隔,如果列表中只有一个元素,那么可以省去方括号
八、附加属性使用“Type.property”格式,其中Type是附加属性的元素的类型
九、属性绑定是指定一个属性的值的声明式表示方法。通过绑定可以使用一个javascript表达式作为属性的值,也可以使用其他属性的值,也可以使用在应用程序中可以获取的值。如果其他属性或数据的值改变了,这个属性的值会自动更新。每当为一个属性分配一个javascript表达式时,便会隐含的使用属性绑定
十、向一个属性分配一个常量也会被认为是一个绑定
十一、PropertyChanges元素可以用在一个状态改变中来修改属性的绑定
十二、如果给已经进行了绑定的属性进行赋值,那么将会移除绑定
十三、在一些高级的情况下,必须明确的使用绑定元素来创建一个绑定(binding)
十四、QML文件中的每一个id值都必须是唯一的,但不同文件中可以有相同的id,因为id值是在文件作用域进行解析的
十五、一个QML文件定义了一个顶级的,独立的QML组件
十六、内联组件使用Component元素声明,Component元素是一个对象,它必须分配到一个属性
十七、一个属性就是QML组件中的一个值,可以被其他对象读取或修改。定义一个属性会为该属性分配新的,独立的存储空间
[default] property <type> <name> [:defaultValue]
type支持类型
QML类型 | C++类型 |
int | int |
bool | bool |
double | double |
real | double |
string | QString |
url | QUrl |
color | QColor |
date | QDateTime |
variant | QVariant |
十八、属性别名会将新什么的属性作为一个已经存在的属性的直接引用
[default] property alias <name>:<alias reference>
十九、使用属性别名需要注意:
1、只有在指定它们的组件创建完成时别名才可用,注意表现在组件本身在创建时不能直接使用属性别名
2、别名引用不能使用在同一个组件中声明的另一个属性别名
3、一个 属性别名可用和现有的属性使用相同的名称
十九、一个函数可用和一个信号关联
二十、添加信号
signal <name>[{[<type><parameter name>[,...]]}]
1、如果信号没有参数,那么括号可以省略
2、向一个组件中添加一个信号,便会自动添加一个信号处理器,它使用"on<SignalName>"来命名,第一个字母需要大写
二一、信号对象有一个connect()函数,可以用来将一个信号关联到一个函数或者其他信号上。当一个信号关联到一个函数上,这个函数会在信号发射时自动调用。也可以将一个信号关联到另一个信号上,这样会转发信号效果
二二、被导入的javascript文件总是使用as关键字来进行限定
二三、如果javascript是从网络资源中获取,则组件的状态会被设置为Loading,直到脚本被下载完毕
二四、大多数的javascript文件被导入一个QML文件是有状态的。一些javascript文件的行为更像库文件,它们提供一组无状态的辅助函数,但是从来不直接操作QML组件实例。javascript可以使用一个pragma来指明一个特定的文件是一个无状态的库。pragma声明必须出现在除了注释外的所有javascript代码前。无状态库文件不能直接访问QML组件实例对象或者属性
二五、如果一个javascript文件需要使用定义在其他javascript文件中的函数,可以通过Qt.include()函数来导入
二六、QML的Component元素提供了一个附加的onCompleted属性可以用来在QML环境完全建立以后切换到启动脚本代码执行。Component.onDestruction附加属性会在组件销毁时触发
二七、在QML中this值是未定义的,要引用任何元素,可以使用其id
二八、QML对象可以在c++中被创建和管理; 也可以在javascript文件中动态创建;也可以使用Loader来动态加载组件
二九、从javascript动态创建对象有两种方式:
1、如果已经有一个在.qml文件中定义的组件,希望动态创建该组件的一个实例,可以调用Qt.createComponent()来动态创建Component对象
2、如果QML本身是在运行时产生的,可以调用Qt.createQmlObject()从QML字符串来创建对象
三十、Qt.createComponent()函数需要将QML文件的URL作为其参数,然后从这个URL上创建一个Component对象,一旦有了一个Component,就可以调用它的createObject()函数来创建该组件的一个实例。这个函数需要指定新对象的父对象。如果想稍后再为其设置父对象,可以安全的设置null作为该函数的参数
三一、Qt.createQmlObject接受3个参数:
1、第一个参数是要创建的QML字符串
2、第二个参数是父对象,必须是在已经存在的一个对象
3、第三个参数是与新对象相关的文件的路径,如果在QML字符串中导入的文件使用的是相对路径,那么需要相对于父对象的文件的路径
三二、可以使用destroy()函数来删除对象。这个函数有一个可选参数,用来设置在销毁对象前的以毫秒问单位的延迟时间。只用动态创建的对象才可以被动态删除
三三、QML对象一般使用下面的顺序进行构造
1、id
2、属性声明
3、信号声明
4、javascript函数
5、对象属性
6、子对象
7、状态
8、状态切换
三四、如果使用了一组属性中的多个属性,那么使用组表示法比使用点表示法清晰
三五、私有属性使用两个下划线开头
import QtQuick 2.12
// 导入js文件,被导入的js文件总是使用as关键字来进行限定
import "factorial.js" as MathFunctions
import "componentCreation.js" as ComponentCreation
Item {
id: rootItem
// 添加属性
// 定义一个属性会为该属性分配新的、独立的存储空间
// [default] property <type> <name> [:defaultValue]
// defautl 可选,表示可以使该属性成为一个类型的默认属性
// type (int, bool, double, real, string, url, color, date, variant)
// defaultValue 可选
property string currentImageSrc: "logo-s.png"
// 私有属性使用两个下划线开头
property real __area: 100
// 属性别名
// 属性别名会将新声明的属性作为一个已经存在的属性的直接引用
// [default] property alias <name> : <alias reference>
property alias currentImage: image
// 添加信号
// signal <name>[([<type><parameter name>[...]])]
signal clicked // 当没有参数是,可以省略括号()
signal hovered()
signal performAction(string action, variant actionArgument)
signal buttonClicked
// 向一个组件添加信号,会自动添加一个信号处理器,使用 on<SignalName> 来命名,第一个字母需要大写
// onClicked
// onHovered
// onPerformAction
// onButtonClicked
Rectangle {
id: rectangle
//属性绑定
//可以绑定一个javascript表达式
//可以绑定其他属性的值
//可以绑定在应用程序中可以获取的值
// 被绑定的值更改了,这个属性的值也会自动更新
width: rootItem.width
height: rootItem.height
// 当一个属性更改值式,它会发送一个信号来告知这个更改,使用on<Property>Changed语法来命名
onWidthChanged: console.log("Width has changed to: ", width)
children: [
Text {
// 使用(.)分组
//font.pixelSize: 12
//font.bold: true
// 使用({})分组
// 如果一组属性中有多个属性,尽量使用分组代替点表示法
font {pixelSize: 12; bold: true}
},
Image {}
]
//PropertyChanges元素可以用在一个状态改变来修改属性的绑定
states: State {
name: "square"
// 当在square状态时,修改rectangle的width属性的绑定为rootItem的height
PropertyChanges {
target: rectangle
width: rootItem.height
}
}
//内联组件使用Component元素声明
resources: [
Component {
id: contactDelegate
Text {
text: qsTr("hello")
}
}
]
ListView {
anchors.fill: parent
delegate: contactDelegate
}
// 如果不存在共享组件,可以这样写
ListView {
anchors.fill: parent
delegate: Component {
Text {
text: qsTr("hello")
}
}
}
// 也可以这样写
ListView {
anchors.fill: parent
delegate: Text {
text: qsTr("hello")
}
}
Image {
id: image
source: rootItem.currentImageSrc
}
// 添加函数
// 函数参数类型默认是variant类型
// function <name>([<parameter name>[....]]) {<body>}
function say(text) {
console.log(text)
}
Button {
id: button
// QML的Component元素提供了一个附加的onCompleted属性可以用来在QML环境完全建立以后切换到启动脚本代码执行
// Component.onDestruction附加属性则会在组件销毁时触发
// connect可以将一个信号关联到一个函数或其他信号上
// disconnect移除关联信号
// button.clicked.disconnect(rootItem.say)
Component.onCompleted: buttonClicked.connect(rootItem.say())
}
}
Rectangle {
width: 100
height: rootItem.height // 属性绑定,当rootItem.height值改变时,Rectangle.height会自动更新
Component.onCompleted: {
height = rootItem.height //属性赋值,当rootItem.height值改变时,Rectangle.height不会自动更新
}
// 当列表中只有一个元素时,可以省去方括号
children: Text{}
}
Rectangle {
id: destroyRect
width: 80
height: 80
NumberAnimation on opacity {
to: 0
duration: 1000
onRunningChanged: {
if (!running) {
console.log("destroying...");
// 可以使用destroy()函数来删除对象,这个函数有一个可选的参数,用来设置在销毁该对象前的以毫秒为单位的延迟十九,默认是0
// 只有动态创建对对象才可以被动态删除
destroyRect.destroy();
}
}
}
}
// 附加属性使用"Type.property"格式,Type表示附加该属性的元素的类型
Component {
id: myDelegate
Text {
text: qsTr("hello")
color: ListView.isCurrentItem ? "red" : "blue"
}
}
ListView {
delegate: myDelegate //ListView元素会附加ListView.isCurrentItem属性到它的每个delegate上
}
MouseArea {
id: mouseArea
}
Component.onCompleted: {
mouseArea.clicked.connect(MathFunctions.logHello())
ComponentCreation.createSpriteObjects()
}
QtObject {
property int a
a: {var a = 12;}
}
}
import QtQuick 2.12
// QML对象一般顺序
//id
//属性声明
//信号声明
//javascript函数
//对象属性
//子对象
//状态
//状态切换
Rectangle {
// id
id: photo
//属性声明
property bool thumbnail: false
property alias image: "logo.png"
// 信号声明
signal clicked
// javascript函数
function doSomething(x) {
return x + photo.width
}
//对象属性
x: 20
y: 20
width: 200
height: 80
// 子对象
Rectangle {
id: border
anchors.centerIn: parent
color: "white"
Image {
id: photoImage
anchors.centerIn: parent
}
}
// 状态
states: State {
name: "selected"
PropertyChanges {
target: border
color: "red"
}
}
// 状态切换
transitions: Transition {
from: ""
to: "selected"
ColorAnimation {
target: border
from: "white"
to: "red"
duration: 200
}
}
}
//大多数js文件被导入一个qml文件是有状态的
//导入一个js文件时默认行为是为每一个QML组件实例提供一个唯一的,独立的备份
// 如果提供了一个无状态的辅助函数库,该库不直接操作QML组件实例,可以使用pragma来指明该库是一个无状态的库
// 无状态的库文件不能直接访问QML组件实例对象或者属性
.pragma library
// 可以通过Qt.include导入其他js库
// Qt.include("script.js")
function logHello() {
console.log("hello")
}
// 从QML字符串创建对象
// 第一个参数是要创建的QML字符串
// 第二个参数是父对象,需要是已经存在的一个对象
// 第三个参数是与新对象相关的文件的路径,如果是相对路径,那么需要相对于定义父对象的文件的路径
var newObject = Qt.createQmlObject('import QtQuick 2.12; Rectangle {color: "red"}', parentItem, "dynamic1");
newObject.destroy(1000); // 动态创建的对象可以通过destroy删除