QML::概念及框架

初识QML

1.01 QML(Qt Meta-Object Language,Qt元对象语言)是一个用来描述应用程序的用户界面的声明式语言。
QML是对JavaScript的一种扩展,可以让开发者和设计者利用一个声明性语法来使用QML元素指定每一个用户界面。
QML完善了JavaScript和Qt现有的基于QObject的类型系统间的整合,在语言级别上添加了对自动属性绑定和透明网络传输的支持。
QML通过QtDeclarative模块便可以完全支持从C十进行扩展。

QML文件是可以直接运行而不需要进行编译的。运行 QML文件的是一个被称为qmlviewer.exe的程序,它在Qt安装目录下的bin目录中。

QML程序中默认使用的是UTF-8编码。可以选择“编辑一选择编码”菜单项,在打开的对话框中选择UTF-8,然后按下“根据编码重新载入”按钮。
1.02 QML 基本类型, 是“类型安全”的。它们只允许分配一个匹配该属性类型的值。
类型 描述
action action类型拥有QAction的所有属性
bool 布尔类型是一个二进制值,有true和false两个值
color 一个color就是一个标准的颜色名称加上引号,例如“red”
date 一个 date 被指定为“YYYY-MM-DD”
double -个double数字包含一个小数点,并使用双精度进行存储
enumeration 一个枚举类型包含一组已命名的值
font font类型包含了QFont的属性
int 整型包含所有的数字,例如0,10,或者一20
list 一个对象列表
point 一个point类型,包含了一个x和一个y属性
real 一个real数字包含了一个小数点,例如1.2或者-29.8
rect 一个rect类型包含了x、y,width和height属性
size 一个size类型包含了width和height属性
string 一个string是一个在引号中的任意格式的文本,例如“Helloworld!”
time 一个time被指定为“hh:mm:ss”
url 一个URL是一个资源定位器,像一个文件名
variant 一个variant类型是一个通用的属性类型
vector3d 一个vector3d类型包含x、y和z属性

1.03 QML的属性类型
QML类型 默认值 c++类型
int 0 int
bool false bool
double 0.0 double
real 0.0 double
string '' QString
url '' QUrl
color #000000 QColor
date 未定义 QDateTime
variant 未定义 QVariant
1.04 属性绑定
1. 使用:对属性进行绑定
Rectangle{
    width: otherItem.width
    height: otherItem.height
}

2. QML扩展了标准的JavaScript引擎,所以任何可用的JavaScript表达式都可以用作属性绑定,
在绑定中可以访问对象属性,调用函数,甚至可以使用Date和Math等内建的JavaScript对象。

anchors.centerIn: parent	//绑定对象属性
width:Math.min(otherItem.width, 10)	//绑定函数
height: calculateMyHeight()
color:{if(width>10)"blue";else "red"}

3. 使用=对已经绑定的对象赋值,如果给已经进行了绑定的属性进行赋值,那么将会移除绑定。
一个属性在一个时间只能拥有一个值,如果任何代码明确的为其设置了值,那么绑定将会被移除。

4. 定义一个新的属性:[default] property <type> <name> [:defaultValue] 
 property string myName: 'xiaoming'
1.05 属性更改通知
当一个属性更改值时,它会发送一个信号来告知这个更改。
要获取这个信号,只需要创建一个信号处理器(signal handler),使用“on<Property>Changed”语法来命名。
例如,Rectangle元素拥有width和color属性,Rectangle对象中定义了两个信号处理器
无论何时属性被修改了,都会自动调用它们。

Rectangle{
    width: 100;height: 100
    onWidthChanged: console.log("width changed")
    onHeightChanged: console.log("height changed")
}
1.06 更改属性绑定(states)与过度(Transitions)
PropertyChanges元素可以用在一个状态改变中来修改属性的绑定。

ColorAnimation过渡由状态的改变触发执行。你可以使用属性的from:和t0:来定义状态改变的指定过渡。
这两个属性就像一个过滤器,当过滤器为tue时,过渡生效。你也可以使用“"来表示任何状态。
from:'';to:'*'表示从任一状态到另一个任一状态的默认值,这意味着过渡用于每个状态的切换。
import QtQuick 2.0
Rectangle {
    id: root
    width: 800
    height: 600
    MouseArea  {
        id:  mouseArea
        anchors.fill:  parent
        onClicked:  {
            light1.state  =  ( light1.state == 'stop' ? "go" : 'stop' )
            light2.state  =  ( light2.state == 'go' ? 'stop' : 'go' )
            console.log('light1.state : ',light1.state);
            console.log('light2.state : ',light2.state);
        }
    }
    Rectangle  {
        id: light1
        x:24; y:15
        width: 100; height: 100
        radius: width/2
        color:  'black'
		
        states:  [
            State  {
                name:  "stop"
                PropertyChanges  { target:  light1; color:  'red' }
            },
            State  {
                name:  "go"
                PropertyChanges  { target:  light2; color:  'green' }
            }
        ]
	/*状态过度,延时2s*/
        transitions: [
            Transition {
                from: "stop"; to: "go"
                ColorAnimation{ target: light1; properties: 'color'; duration: 2000 }
                ColorAnimation{ target: light2; properties: 'color'; duration: 2000 }
            }
        ]
    }
    Rectangle  {
        id: light2
        x:24; y:135
        width: 100; height: 100
        radius: width/2
        color:  'black'
    }
}
1.07 绑定元素
从c++中暴露的属性(system.brightness)绑定到一个来自 QML的值(slider.value)就需要使用到绑定元素。

Binding{
     target: system
     property: 'brightness'
     value: slider.value
}
1.08 属性别名
1. 属性别名是更高级的属性声明形式。
2. 与定义一个属性不同,定义一个属性会为该属性分配新的、独立的存储空间,
而 属性别名 会将新声明的属性(称为别名属性) 作为一个已经存在的属性 (被别名的属性)的直接引用。
对别名属性的读/写操作 等价于 对被别名的属性进行读/写操作。
3. 属性别名对于允许外部对象直接修改和访问一个组件中的子对象是很有用的
4. 属性别名的声明语法如下:
[defaul] tproperty alias <name>:<alias reference>
1.09 组件中添加函数
QML组件中可以定义JavaScript代码的函数,这些函数可以在内部调用,也可以被其他对象调用。

Rectangle {
    id: rootRect
    width: 800
    height: 600
    visible: true

    function say(test){
        console.log('said: ', test);
    }

    MouseArea {
        anchors.fill: parent
        onClicked: rootRect.say("hello world")
    }
}
1.09 组件中添加信号
1. 当一个事件发生时,可以使用信号通知其他对象。
定义一个新的信号的语法如下:
signal <name>[([<type><parameter name>[,...]])] 如:
Item{
	signal clicked
	signal hovered()
	signal performAction(string action, variant actionArgument)
}

2. 发射信号就是简单调用它,就像操作函数一样。
Rectangle {
	id: rect1
	signal buttonClicked
	width: 100; height:100
	MouseArea {
		anchors.fill: parent
		onClicked: rect1.buttonClicked()
	}
}
1.10 将信号关联到其他函数和信号上
1. 信号对象有一个connect()函数,可以用来将一个信号关联到一个函数或者其他的信号上。
当一个信号关联到一个函数上,这个函数会在信号发射时自动调用。
/*Button.qml*/
import QtQuick 2.0
Rectangle{
    id: rect
    signal buttonClicked (int xPos, int yPos)
    width: 100; height: 100
    color: 'red'
    MouseArea {
        anchors.fill: parent
        onClicked: rect.buttonClicked(mouse.x, mouse.y)
    }
}
import QtQuick 2.12
import QtQuick.Window 2.12
Rectangle {
    id: rootRect
    width: 800
    height: 600
    visible: true
    Item {
        id: item
        width: 200; height: 200

        function myMethod(){
            console.log('Button was clicked')
        }
        Button {
            id:button
            anchors.fill: parent
            Component.onCompleted: buttonClicked.connect(item.myMethod)
        }
    }
}
2. 在大多数情况下,使用信号处理器来接收信号就足够了,因为这里的代码使用connect()函数比以前使用onButtonClicked处理器没有任何的优势。
然而,如果要动态创建对象或者集成JavaScript代码,就会发现connect()函数很有用。

posted @ 2019-12-18 15:15  osbreak  阅读(661)  评论(0编辑  收藏  举报