(基于qt 5.3.1)
一、Qt Quick入门
1.启动Qt Quick App的两种方式
窗口标题、图标等由qml控制
main.cpp用QQmlApplicationEngine:
//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])//主函数必须带参
{
QGuiApplication app(argc, argv);//app的参数和main的参数对应
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
// "qrc:///"表示该qt工程的根目录
return app.exec();
}
main.qml用Window:
//main.qml
import QtQuick 2.2
import QtQuick.Window 2.1
Window {
visible: true
width: 360
height: 360
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
Text {
text: qsTr("Hello World")
anchors.centerIn: parent
}
}
窗口标题、图标由c++代码控制
main.cpp用QQuickView:
#include <QGuiApplication>
#include <QQuickView> //头文件
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView viewer;
viewer.setResizeMode(QQuickView::SizeRootObjectToView);
viewer.setSource(QUrl("qrc:///main.qml"));
viewer.show();
return app.exec();
}
main.qml用Item(Rectangle等):
import QtQuick 2.2
import QtQuick.Window 2.1
Rectangle {
visible: true
width: 360
height: 360
Text {
text: qsTr("Hello World")
anchors.centerIn: parent
}
}
注意:此处不能调用Qt.quit()。
2.Window对象
visibility:控制窗口最小化、最大化、全屏等。
直接在Window里面加入:
visibility: Window.Minimized
visibility: Window.Maximized
visibility: Window.FullScreen
color:"blue","#FFFFFF"
opacity:设置窗口透明度,取值范围0~1
title:标题
3.Rectangle:
color: Qt.rgba(r,g,b,a) ,rgba在0~1之间,rgb表示每种颜色所占的比例,a表示颜色的深浅。
gradient:渐变填充,优先级高于color。每一个GradientStop为一个确定颜色的位置,在两个确定颜色之间渐变填充。
Rectangle {
width: 320
height: 480
gradient: Gradient{
GradientStop{
position:0.0
color:"black"
}
GradientStop{
position:0.33
color:"blue"
}
GradientStop{
position:1.0
color:"white"
}
}
}
rotation:旋转角度,可以用rotation:90实现横向渐变。
4.Item
Item是Rectangle的父类。
x,y:位置。
z:图层的优先级。z越大,越在其他图层上面。
clip:在父类设定,默认为false,当设置为true时自动调整子类的大小使之不会跑到父类外面去。
5.anchors
利用图元之间的相对位置布局。
anchors.left:parent.left表示当前图元的最左侧和它父类的最左侧重合。
anchors.leftMargin:20表示当前图元的最左侧向右移动20像素。
anchors.fill:parent表示当前图元填满它的父类。
anchors.centerIn:parent表示当前图元居中放置于它的父类中。
Rectangle {
width: 300
height: 200
Rectangle{
id:rect1
anchors.left:parent.left
anchors.leftMargin: 20
anchors.top:parent.top
anchors.topMargin: 20
width:120
height:120
color:"red"
}
Rectangle{
anchors.left: rect1.right
anchors.leftMargin: 20
anchors.top: rect1.top
width:120
height:120
color:"blue"
}
}
Rectangle {
width: 300
height: 200
Rectangle{
color:"blue"
anchors.fill:parent
border.width: 6
border.color: "black"
Rectangle{
anchors.centerIn: parent
width:120
height:120
radius:8
border.width: 2
border.color: "white"
antialiasing: true //抗锯齿
color:"red"
}
}
}
6.Keys
响应键盘。
focus:焦点,要让某个元素响应按键,必须把它的focus设成true。
Keys.enabled:键盘使能
Keys.onPressed:检测到某个键被按下时,就将event.key设成Qt.Keys_x,后者是宏,为那个键对应的ASCII码。
按某个数字键,就显示某个数字的程序:(按Esc键退出)
注意:默认为中文输入法,要手动切换。
import QtQuick 2.2
import QtQuick.Window 2.1
Window{
visible: true
height: 360
width: 480
Rectangle{
width: 480
height: 360
color:"#c0c0c0"
focus:true
Keys.enabled: true
Keys.onEscapePressed: Qt.quit()
Keys.onBackPressed: Qt.quit()
Keys.onPressed: {
switch(event.key){
case Qt.Key_0:
case Qt.Key_1:
case Qt.Key_2:
case Qt.Key_3:
case Qt.Key_4:
case Qt.Key_5:
case Qt.Key_6:
case Qt.Key_7:
case Qt.Key_8:
case Qt.Key_9:
event.accepted=true
keyView.text=event.key-Qt.Key_0;
break;
}
}
Text{ //可以写在后面
id:keyView
font.bold: true
font.pixelSize: 24
text: qsTr("text")
anchors.centerIn: parent
}
}
}
7.Text
显示文本。
wrapMode:换行方式,WordWrap在两个单词之间换行,WrapAnywhere可以在单词内部换行。
font:字体设置,font.bold:true表示加粗,font.pixelSize:24表示一个字占24像素,font.underline:true表示下划线。
text:文本内容。
style:文字风格,有Outline,Raised,Sunken等。
stylecolor:描边的颜色。
font.family: "楷体" 设置字体
8.Button
需要引入import QtQuick.Controls 1.2
用onClicked表示按下按钮后的操作。
这个操作相当于c++代码。
Button{
text:"Quit"
anchors.centerIn: parent
onClicked:{
Qt.quit();
}
}
checkable:设置Button是否可选。
iconSource:用URL的方式指定图标图片。
focus:如果设置为true,则空格表示按下此按钮。
style:设置按钮的风格。
style:ButtonStyle 有background,control和lable三个属性,可以用于设置按钮的背景,并随操作而改变。
implicitWidth: 必须要加implicit。
implicitHeight:
control.pressed:是否按下按钮
control.hovered:鼠标是否悬停在按钮上
style: ButtonStyle{
background: Rectangle{
implicitWidth: 70
implicitHeight: 25
border.width: control.pressed?2:1
border.color:
(control.hovered||control.pressed)?"green":"#888888"
}
}
9.Image
显示照片。
sources:照片的来源,可以是本地照片也可以是网络照片,本地照片前要加"file:///"。
Window{
visible: true
height: 360
width: 480
Image{
anchors.fill: parent
source: "file:///C:/Users/doujihu/Desktop/其他/photos/照片.jpg"
}
}
默认同步显示图片,要开启异步设置:asynchronous: true
10.busyIndicator
等待的圆圈标记。
running:true 显示等待标记
style:BusyIndicatorStyle{} 用于设置等待图片。
11.FileDialog
需要引入import QtQuick.Dialogs 1.1
文件对话框,用于保存\打开文件。
id.open():弹出文件对话框
title:文件对话框的标题
nameFilters:["Image Files(*.jpg *.png *.gif)"]
文件过滤器,只有这些后缀名的文件能被选中。
onAccepted:{}
选中后执行的操作
id.fileUrl:文件地址,以file:///开头
string类的slice方法:s.slice(a,b)截取从a到b的部分,可以省略a或b。
FileDialog{
id:fileDialog
title:"please choose"
nameFilters: ["Image Files(*.jpg *.png *.gif)"]
onAccepted:{
imageViewer.source=fileDialog.fileUrl;
var imageFile=new String(fileDialog.fileUrl);
imagePath.text=imageFile.slice(8);
}
}
二、ECMAScript
弱类型:类型都叫var,一个变量可以赋值不同的数据类型。
语句后可以不写分号,以换行作为结尾标记。
原始类型:Undefined,Null,Boolean,Number,String,Object
typeof 运算符:返回类型名
Undefined类型只有一个underfined值,表示未初始化的变量,没有明确返回值的函数,也返回undefined。
Null类型只有一个值null。
Boolean相当于bool。
Number支持十六进制,八进制,科学记数法等。最大值为Number.MAX_VALUE,最小值为Number.MIN_VALUE。如果超过最大值,会返回Infinity,可以用isFinit()判断是否有穷。NaN:表示强制类型转换的对象不是纯数字,只能用isNaN()判断。
String字符串类型,没有char。String类的变量是只读的,不能通过S[0]='a'来修改。
Number.toString(base=10) 把数字以base为基转化为字符串。
parseInt(String)和parseFloat(String) 从字符串的最左边开始,到第一个非数字字符为止,提取数字。
Boolean() 对于非空对象,返回true,否则返回false。
Number() 对整个值转换,如果整个值不是有效数字,返回NaN。
Object类:所有类的基类。
类成员可以动态添加:
Window {
height:480
width:640
Component.onCompleted: {
var person= new Object();
person.name="zhang san"; //person原来没有name成员
person.year=20;
console.log(person.name);
console.log(person.year);
}
}
也可以添加方法:
Component.onCompleted: {
var person= new Object();
person.name="zhang san";
person.year=20;
person.show = function show(){ \\用等号声明函数
console.log("name:",this.name,"\nyear:",this.year);
\\this的使用和c++一样
}
person.show();
}
对象的属性和方法可以用类似于map的下标访问。
console.log(person["name"]);
person["show"](); //相当于person.show();
使用for...in...可以遍历一个对象的属性。
for(var i in person){
console.log(i,":",person[i]);
}
对象的字面量表示法:可以直接用大括号加冒号实例化类。
Window {
height:480
width:640
Component.onCompleted: {
var person = {
"name": "zhangsan",
"year": 20, //注意:两个成员之间必须用逗号隔开
"show": function show(){
console.log(this.name,":",this.year);
}
}
person.show();
}
}
String类:
str.indexOf("string",first=0):从first开始查找"string",返回string在str中的第一个字符的下标,如果搜不到,输出-1。
str.search("string") :总是从头开始查找"string",支持正则表达式,返回下标。
str.match("string"):从头开始匹配"string",支持正则表达式,返回存放所有子串的数组。
str.slice(a,b):提取[a,b)的子串。若为负数,则表示倒数几个字符。(和python类似)。
str.substr(a,b):从a开始,提取长度为b的子串。
str.toLowerCase():转化成小写。
str.replace("str1","str2"):把str中的第一个str1换成str2,如果想把str中的str1都换成str2,要用正则表达式/str1/g。
str.split(str1):以str1为分隔符,将str划分,返回数组(不含str1)。
str.arg(i):把%d换成i。console.log("%1+%2=%3".arg(3).arg(4).arg(7));
正则表达式:
/"String"/i等价于RegExp("String","i"),"String"叫模式,"i"叫修饰符。
修饰符:
"i":忽略大小写。
"g":查找所有符合条件的匹配,而不是在找到第一个匹配后停止。
"m":跳过换行符匹配。
元字符:
".":匹配除换行符外的任意字符。
"\w":匹配字母,数字,下划线或汉字。
"\s":匹配任意空白字符。
"\S":匹配任意非空白字符。
"\d":匹配数字字符。
"\D":匹配非数字字符。
"\b":匹配单词的开始或结束。
"^":匹配字符串的开始。
"$":匹配字符串的结束。
量词:
"*":重复零次,一次或多次。
"+":重复一次或多次。
"?":重复零次或一次。
"{n}":重复n次。
"{n,}":重复n次或多次。
"{n,m}":重复n到m次。
console.log(str.match(/^We.*/mg));
表示匹配所有以We开头的行。
字符集:[xyz]匹配x,y,z,[0-9]匹配0到9。
转义字符:*,.,\。
正则表达式可用于String类的search(),match(),replace(),split()方法。
Array类:可变数组,类型可以不同。
var a=[1,2,3,4,5];
a.push(6,7,8,9):向数组末尾插入一个或多个元素,返回数组长度。
a.pop():删除并返回最后一个元素。
用越界下标也可以扩充数组,直接a[6]=7即可,此时a[5]=undefined。
a.shift():删除并返回a[0]。
a.unshift(6,7,8,9):从a[0]开始塞进去若干元素。
a.sort(cmp):对数组排序。
数组的下标可以为负数,负数下标不会受到任何方法的影响。如a[-1]=6。
a.join(str):以str为分隔符,将a转化为字符串。
a.concat(b):返回数组a连接数组b形成的新数组。注意:不能写成a+b。
a.slice(start,end):返回[start,end)的新数组。
a.splice(index,num):删除a从index开始的num个元素,并返回它们组成的数组。
Math类:
Math.random() 返回0-1之间的随机数。
Date类:
Date()返回现在时间构成的字符串。
Date.now()返回1970.1.1至今的毫秒数,可以用来做计时器。
和c++不一样的是,对象使用完不用delete,直接array=null即可。
函数:
function 函数名(变量名1,...){}
变量名前面不用写类型,任何一个函数都有返回值,返回值可以为任何类型。
运算符:
===:全等于,值和类型都一样。为了防止null==0。
">>>":带零扩展的右移,移动后最左侧补0,负数右移后变成正数。
void():强制转化为undefined。
str instanceof String 判断str是否是String类型,如果是,返回true,可以用于一般的Object(typeof不行)。
console:
console.time(tag):启动计时器,tag是个字符串。
console.time(tag):停止tag对应的计时器并输出时间。
Global,Math,JSON不需要实例化就可以使用,被称作内置对象。
QML基本类型:
url:资源地址,可以是本地地址,相对地址和网络位置。
encodeURI("url"):把url中无效的空格自动替换成/
list:储存对象的数组,如item的children属性,children[i]表示它的第i个孩子。
enumeration:枚举类型
Qt.openUrlExternally("url"):打开url,可以是本地文件,也可以用浏览器打开网址。
三、Qt Quick 信号处理
信号处理器:on<Signal>:{代码块}
附加信号处理器:<别的类型>.on<Signal>:{代码块}
如在Rectangle里面用Keys.onEscapePressed:{},表示按下Esc键的情况。
Component信号:
Component.onCompleted:组件创建完成时执行的操作。
Component.onDestruction:组件销毁时执行的操作。
Connections:将多个对象和一个信号连接,或者在对象的作用域外使用它的信号。
Connections{
target:发出信号的对象名
on<Signal>:{
代码块;
}
}
(当然也可以在Button里面直接写)
信号分为两类:输入操作(鼠标,键盘等)产生的信号,属性改变产生的信号(on<Property>Changed)。
自定义信号:相当于一个返回值为Signal的函数
Signal 信号名(属性名1 参数1,属性名2 参数2...);
当需要发出这个信号时,调用此函数。
在Connection里面用on信号名对这个信号进行处理,这里可以使用Signal函数的参数。
Loader:加载组件。
Loader.sourceComponet表示它使用哪个已有的组件来加载新的组件,这个已有的组件叫item。
onLoaded是加载完成的信号。
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
Text{
id:coloredText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top:parent.top
anchors.topMargin: 4
text:"Hello World!"
font.pixelSize: 32
}
Component{
id: colorComponent
Rectangle{
id:colorPicker
width:50
height:30
signal colorPicked(color clr);
MouseArea{
anchors.fill: parent
onPressed: colorPicker.colorPicked(colorPicker.color)
}
}
}
Loader{
id:redLoder
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
sourceComponent: colorComponent
onLoaded:{
item.color="red";
}
}
Loader{
id:blueLoder
anchors.left: redLoder.right
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
sourceComponent: colorComponent
onLoaded:{
item.color="blue";
}
}
Connections{
target: redLoder.item
onColorPicked:{
coloredText.color=clr;
}
}
Connections{
target: blueLoder.item
onColorPicked:{
coloredText.color=clr;
}
}
}
}
signal.connect(func1,func2,...):把signal对象连接到另外的信号或方法上,当信号发射时,连接到信号上的其他信号或方法就会被调用。用于一个信号连接多个方法。
Rectangle{
id: forwarder
anchors.fill: parent
signal send()
onSend: console.log("Send!");
MouseArea{
id:mousearea
anchors.fill: parent
onClicked: console.log("Mouse!");
}
Component.onCompleted: {
mousearea.clicked.connect(send);
//当clicked被触发时,调用send方法,即send也被触发。
}
}
鼠标:
在一个item内部用MouseArea对象。
enable:true表示开始处理鼠标事件。
acceptedButtons设定接受哪些按键,中间用或隔开:Qt.LeftButton|Qt.RightButton|Qt.MidButton
hoverEnabled:true表示开始处理鼠标悬停事件。
鼠标信号:
clicked:单击,在内部用mouse.button读取哪个键,mouse.x和mouse.y为鼠标坐标。
doubleClicked:双击。
pressed:按住鼠标。
pressAndHold:长按鼠标。
released:松开鼠标。
entered:鼠标进入事件区域。
exited:鼠标离开事件区域。
mouse.accepted=true:鼠标事件终止,不再往下传递。
键盘:
必须先把focus设成true。
Keys.enabled:true表示开始处理按键。
Keys.onPressed:一般按键信号,有一个叫event的参数。
Keys.onXXXPressed:特殊按键信号,如空格,回车等。
Keys.forwardTo:[a,b,c] 表示传递给列表内的对象,如果某个对象accept了某个按键,那么列表中排在它后面的对象就不会收到该按键事件。
event.accepted:处理完成标记。
event.key:按下的键,用于和Qt.Key_x比较。
Keys.priority:设置Keys附加属性的优先级。Keys.BeforeItem在Item之前处理按键(默认),Keys.AfterItem在Item之后处理按键。比如Item自带按键处理,如果在Item之后处理按键,按键会被Item吞掉,如CheckBox。
Window {
height:640
width:480
visible:true
Rectangle{
id:rect1
anchors.fill: parent
color:"gray"
focus:true
Keys.enabled: true
Keys.onEscapePressed: Qt.quit();
Keys.forwardTo: [moveText,likeQt]
Keys.priority: Keys.BeforeItem
Text{
id:moveText
x:20
y:20
width:200
height:30
text:"Moving Text"
color:"blue"
font.bold: true
font.pixelSize: 24
Keys.enabled: true
Keys.onSpacePressed: {
rect1.color="black";
event.accepted=true;
}
Keys.onPressed: {
switch(event.key){
case Qt.Key_Left:
if(x>=5)
x-=10;
break;
case Qt.Key_Right:
if(x<=330)
x+=10;
break;
case Qt.Key_Down:
if(y<=600)
y+=10;
break;
case Qt.Key_Up:
if(y>=5)
y-=10;
break;
default:
return;
//必须return,否则switch外面的accepted会把信号吃掉,checkbox收不到空格信号
}
event.accepted=true;
}
}
CheckBox{
id:likeQt;
text:"Like Qt Quick"
anchors.left: parent.left
anchors.leftMargin: 10
anchors.bottom: parent.bottom
anchors.bottomMargin: 10
z:1
}
}
}
计时器:Timer
running:true 计时器开始工作
onTriggered:每经过一个计时周期产生一个信号。
interval:计时周期,默认为1000ms。
repeat:true 可以复位
triggeredOnStart:true 启动后立刻触发一次。
start() stop() restart()
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
color:"gray"
QtObject{
id:attrs
property int counter; //设置临时变量,不能用var。
Component.onCompleted: {
attrs.counter = 10;
}
}
Text{
id: countShow
anchors.centerIn: parent;
color: "blue"
font.pixelSize: 40
}
Timer{
id: countDown
interval: 1000;
repeat :true
triggeredOnStart: true
onTriggered: {
countShow.text=attrs.counter;
attrs.counter--;
if(attrs.counter<0){
countDown.restart();
attrs.counter=10;
}
}
}
Button{
id:startButton
anchors.top: countShow.bottom
anchors.topMargin: 20
anchors.horizontalCenter: countShow.horizontalCenter;
text:"Start"
onClicked:{
attrs.counter=10;
countDown.start();
}
}
}
}
四、组件与动态对象
1.Component
既可以定义在单独的.qml文件中,也可以在其他item里面定义。
Component只能包含一个顶层Item,而且除了这个Item外只能有id。它自己不可见,必须通过Loader实例化后才可见。定义在单独文件中的Component,文件名就是组件名,组件名的首字母必须大写。
KeyNavigation.left/right/tab:XXX 把focus传递给XXX。
一个完整的实例:
ColorPicker.qml:
//ColorPicker.qml
//增加了用回车和空格选定的功能
import QtQuick 2.2
Rectangle {
id: colorPicker
width: 50
height: 30
signal colorPicked(color clr);
function configureBorder(){ //当focus改变时,用来改变边框粗细和颜色的函数
colorPicker.border.width=colorPicker.focus?2:0
colorPicker.border.color=colorPicker.focus?"yellow":"black"
}
MouseArea{
anchors.fill: parent
onClicked:{
colorPicker.colorPicked(colorPicker.color);
mouse.accepted=true;
colorPicker.focus=true;
}
}
Keys.onReturnPressed: {
colorPicker.colorPicked(colorPicker.color);
event.accepted=true;
}
Keys.onSpacePressed: {
colorPicker.colorPicked(colorPicker.color);
event.accepted=true;
}
onFocusChanged: configureBorder();
Component.onCompleted: configureBorder();
}
main.qml:
//main.qml
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
Text{
id:coloredText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top:parent.top
anchors.topMargin: 4
text:"Hello World!"
font.pixelSize: 32
}
function setTextColor(clr){ //染色函数
coloredText.color=clr;
}
ColorPicker{
id:redColor
color:"red"
focus:true
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
KeyNavigation.right: blueColor //按右方向键把focus传递给blueColor
KeyNavigation.tab: blueColor
}
ColorPicker{
id:blueColor
color:"blue"
anchors.left: redColor.right
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
KeyNavigation.left: redColor
KeyNavigation.right: pinkColor
KeyNavigation.tab: pinkColor
}
ColorPicker{
id:pinkColor
color:"pink"
anchors.left: blueColor.right
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
KeyNavigation.left: blueColor
KeyNavigation.tab: redColor
}
Component.onCompleted: {
redColor.colorPicked.connect(setTextColor);
blueColor.colorPicked.connect(setTextColor); //这里是函数名,不是func()
pinkColor.colorPicked.connect(setTextColor);
}
}
}
2.Loader
source:加载qml文档。
sourceComponent:加载Component对象。
item:指向它加载组件对应的顶层对象,如它加载的组件是个Rectangle,则用item可以访问那个Rectangle的属性和信号。
Loader.item可以作为Connections的target来处理信号。
Loader的尺寸和位置默认与Component一样,可以单独在Loader内修改。
注意Loader的focus和它对应的item的focus不一样,在Loader里可以直接用item.focus=focus来传递,但是在item中要单独设一个property Item loader,用它的focus来保存它对应Loader的focus。
用Loader实现与上例相同的功能,但是逻辑更复杂:
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
Text{
id:coloredText
anchors.horizontalCenter: parent.horizontalCenter
anchors.top:parent.top
anchors.topMargin: 4
text:"Hello World!"
font.pixelSize: 32
}
Component{
id: colorComponent
Rectangle{
id:colorPicker
width:50
height:30
signal colorPicked(color clr);
property Item loader;
border.width: focus?2:0
border.color: focus?"yellow":"black"
MouseArea{
anchors.fill: parent
onClicked: {
colorPicker.colorPicked(colorPicker.color);
loader.focus=true;
}
}
Keys.onReturnPressed: {
colorPicker.colorPicked(colorPicker.color);
event.accepted=true;
}
Keys.onSpacePressed: {
colorPicker.colorPicked(colorPicker.color);
event.accepted=true;
}
}
}
Loader{
id:redLoder
width:80
height:60
focus:true
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
sourceComponent: colorComponent
KeyNavigation.right: blueLoder
onLoaded:{
item.color="red";
item.focus=true;
item.loader=redLoder
}
onFocusChanged: item.focus=focus;
}
Loader{
id:blueLoder
anchors.left: redLoder.right
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
sourceComponent: colorComponent
KeyNavigation.left: redLoder
onLoaded:{
item.color="blue";
item.loader=blueLoder;
}
onFocusChanged: item.focus=focus;
}
Connections{
target: redLoder.item
onColorPicked:{
coloredText.color=clr;
}
}
Connections{
target: blueLoder.item
onColorPicked:{
coloredText.color=clr;
}
}
}
}
3.动态创建和销毁组件
在Rectangle(rootItem)加一个标记位:property bool colorPickerShow: false;
把sourceComponent改成undefined,这个组件就隐藏了。
相当于一个状态机:当click时,根据现态是true还是false决定如何转移。
Button{
id:ctrlButton
text:"Show"
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
onClicked:{
if(rootItem.colorPickerShow){
redLoader.sourceComponent=undefined;
blueLoader.sourceComponent=undefined;
rootItem.colorPickerShow=false;
ctrlButton.text="Show";
}
else{
redLoader.sourceComponent=colorComponent;
blueLoader.sourceComponent=colorComponent;
redLoader.focus=true;
rootItem.colorPickerShow=true;
ctrlButton.text="Hide";
ctrlButton.anchors.leftMargin=400;
}
}
}
4.用ECMAScript动态创建对象
Qt.creatComponent("XXX.qml"):创建一个XXX.qml组件并返回该组件。
Component.creatObject(parent,{"属性1":XXX,"属性2":YYY,...}):以parent为父类,以大括号内的内容为属性初始值,创建一个该组件的实例并返回该实例。
rootItem.component.status==Component.Ready 判断组件是否创建成功。
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
Window {
height:640
width:480
visible:true
Rectangle{
id: rootItem
anchors.fill: parent
property int count: 0;
property Component component: null;
Text{
id:coloredText;
text: "Hello World!"
anchors.centerIn: parent
font.pixelSize: 24
}
function changeTextColor(clr){
coloredText.color=clr;
}
function createColorPicker(clr){
if(rootItem.component==null){
rootItem.component=
Qt.createComponent("ColorPicker.qml");
}
var colorPicker;
if(rootItem.component.status==Component.Ready){
colorPicker=rootItem.component.createObject(rootItem,
{"color":clr,"x":rootItem.count*55,"y":10});
colorPicker.colorPicked.connect(rootItem.changeTextColor);
//clr这个参数从createColorPicker传递到changeTextColor
}
rootItem.count++;
}
Button{
id: add
text:"add"
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
onClicked:{
//下面这一行书上写错了
rootItem.createColorPicker(Qt.rgba(Math.random(),
Math.random(),Math.random(),1));
}
}
}
}
5.销毁动态创建的对象
对于Loader创建的对象,直接把source设为空串或者把sourceComponent设置成undefined即可自动销毁。
对于Qt方法创建的对象,调用其destroy(time=0ms)方法即可销毁,time为销毁延迟的时间。
利用数组实现组件的删除:
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
Window {
height:640
width:480
visible:true
Rectangle{
id: rootItem
anchors.fill: parent
property int count: 0;
property Component component: null;
property var array: new Array();
Text{
id:coloredText;
text: "Hello World!"
anchors.centerIn: parent
font.pixelSize: 24
}
function changeTextColor(clr){
coloredText.color=clr;
}
function createColorPicker(clr){
if(rootItem.component==null){
rootItem.component=
Qt.createComponent("ColorPicker.qml");
}
var colorPicker;
if(rootItem.component.status==Component.Ready){
colorPicker=rootItem.component.createObject(rootItem,
{"color":clr,"x":rootItem.count*55,"y":10});
colorPicker.colorPicked.connect(rootItem.changeTextColor);
rootItem.array.push(colorPicker);
}
rootItem.count++;
}
Button{
id: add
text:"add"
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
onClicked:{
rootItem.createColorPicker(Qt.rgba(Math.random(),
Math.random(),Math.random(),1));
}
}
Button{
id: del
text:"del"
anchors.left: add.right
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
onClicked:{
rootItem.array[rootItem.array.length-1].destroy();
rootItem.array.pop();
rootItem.count--;
}
}
}
}
五、元素布局
布局定位器:只改变父类的大小,不改变孩子们的尺寸。
布局管理器:根据界面尺寸变化自动调整孩子们的尺寸。
1.Row和Column
用锚布局设置行的位置,用spacing属性设定Item的间隔,用layoutDirection属性指定布局方向,默认为从左到右,设定为Qt.RightToLeft时从右向左。
Column一样。
2.Grid和Flow
网格,由rows和columns设置行列数,默认为x行4列;rowSpacing和columnSpacing指定行列间距。
flow属性为放置方法,默认为从左到右,放满一行再放下一行;可以改成Grid.TopToBottom。
Flow:按照自身的宽和高是否超出边界而自动折行。
3.GridLayout
高级的Grid。
要引入import Qtquick.Layouts 1.1
Layout.fillWidth: true 填充一行的所有剩余空间,要提前确定Layout的宽度。
RowLayout、ColumnLayout同理。
六、常用元素
1.TextInput
输入一行文本。要设置focus:true才能有效。
maximumLength:设置编辑框允许输入字符的最大长度。
echoMode:回显属性,默认为TextInput.Normal,可以设置为TextInput.Password:显示黑圆圈(用Passwordcharacter设置),TextInput.NoEcho:不回显。
inputMask:限制输入字符的格式,如000.000.000.000可以作为ip地址。
IntValidator、RegExpValidator分别为整数和正则表达式验证器,用于限制输入字符的格式。
selectByMouse:true 可以用鼠标选择编辑框内的文字。
当按下回车键或编辑框失去焦点时,会发出accepted信号,可以用onAccepted来处理。
2.TextField
高级版TextInput。
textColor:设置文本颜色,注意不是color。
控件TextFieldStyle的background属性可以设定TextField的背景图案。
TextField{
id:input
style: TextFieldStyle{
textColor:"black"
background: Rectangle{
radius:2
implicitWidth: 100
implicitHeight: 24
border.color: "yellow"
border.width: 1
}
}
}
3.TextEdit
多行文本编辑框。
warpMode:TextEdit.WordWrap 在单词边界处折行。
4.TextArea
可以用TextAeraStyle的background属性设定背景色,但是不能设置背景图案,只能用TextEdit底下放个z序较小的Rectangle对象来实现。
selectionColor:选中字符边框的颜色。
selectedTextColor:选中字符的颜色。
TextArea支持鼠标和键盘的滚动。
5.RadioButton
单选。
需要引入import QtQuick.Controls 1.2
ExclusiveGroup:互斥分组,分组内的元素只能选一个。通过按钮类的exclusiveGroup属性声明是哪个分组。
XXX.current:表示XXX当前被选中的元素。
text:显示文本
checked:显示RadioButton是否被选中
hovered:指示鼠标是否悬停在按钮上
pressed:按钮按下时为true。
activeFocusOnPress:按钮获得焦点时为true。
RadioButtonStyle组件:定制按钮样式。
background:定制选项的背景。
indicator:定制选中的指示图标。
label:定制单选按钮的文本。
control:使用style的RadioButton对象,如control.text为对应按钮旁边的文字。
spacing:图标和文本之间的间隔。
当选中某个选项时,发送clicked信号,可以用onClicked处理。
单项选择示例:
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
color:"white"
Rectangle{
id:resultHolder
color:"#a0a0a0"
width:200
height:60
anchors.centerIn: parent
visible: false
z:2
opacity: 0.8
border.width: 2
border.color: "#808080"
Text{
id:result
anchors.centerIn: parent
font.pointSize: 20
color:"#0500ff"
font.bold: true
}
}
ExclusiveGroup{
id:mos;
}
Component{
id:radioStyle
RadioButtonStyle{
background:Rectangle{
opacity: 0.8
color:"#a0a0a0"
border.width: 2
border.color: control.activeFocus?"yellow": "#808080"
}
indicator:Rectangle{
visible:false
}
label: Text{
font.pixelSize: 24
color: control.activeFocus? "blue":"black"
text: control.text
}
MouseArea{
anchors.fill: parent
enabled: true
onDoubleClicked:{
console.log(666);
result.text=choose1.text;
resultHolder.visible=true;
}
}
}
}
Text{
id:notation
text:"请选择喜欢的文字游戏:"
color:"black"
font.pixelSize: 32
anchors.top:parent.top
anchors.topMargin:45
anchors.left: parent.left
anchors.leftMargin: 45
}
RadioButton{
id:choose1
text:"ever17"
exclusiveGroup: mos
anchors.top:notation.bottom
anchors.topMargin: 4
anchors.left: notation.left
anchors.leftMargin: 20
focus:true
activeFocusOnPress: true
style:radioStyle
property bool click : false //实现双击确定
onCheckedChanged: {
if(!this.checked) this.click=0;
}
onClicked: {
if(this.click){
result.text=this.text;
resultHolder.visible=true;
this.click=false;
}
else this.click=true;
}
Keys.enabled: true
Keys.onReturnPressed: {
result.text=this.text;
resultHolder.visible=true;
}
Keys.onEscapePressed: {
resultHolder.visible=false;
}
KeyNavigation.up: choose4
KeyNavigation.down: choose2
}
RadioButton{
id:choose2
text:"素晴日"
exclusiveGroup: mos
anchors.top:choose1.bottom
anchors.topMargin: 4
anchors.left: choose1.left
activeFocusOnPress: true
style:radioStyle
property bool click : false //实现双击确定
onCheckedChanged: {
if(!this.checked) this.click=0;
}
onClicked: {
if(this.click){
result.text=this.text;
resultHolder.visible=true;
this.click=false;
}
else this.click=true;
}
Keys.enabled: true
Keys.onReturnPressed: {
result.text=this.text;
resultHolder.visible=true;
}
Keys.onEscapePressed: {
resultHolder.visible=false;
}
KeyNavigation.up: choose1
KeyNavigation.down: choose3
}
RadioButton{
id:choose3
text:"Clannad"
exclusiveGroup: mos
anchors.top:choose2.bottom
anchors.topMargin: 4
anchors.left: choose2.left
activeFocusOnPress: true
style:radioStyle
property bool click : false //实现双击确定
onCheckedChanged: {
if(!this.checked) this.click=0;
}
onClicked: {
if(this.click){
result.text=this.text;
resultHolder.visible=true;
this.click=false;
}
else this.click=true;
}
Keys.enabled: true
Keys.onReturnPressed: {
result.text=this.text;
resultHolder.visible=true;
}
Keys.onEscapePressed: {
resultHolder.visible=false;
}
KeyNavigation.up: choose2
KeyNavigation.down: choose4
}
RadioButton{
id:choose4
text:"白色相簿2"
exclusiveGroup: mos
anchors.top:choose3.bottom
anchors.topMargin: 4
anchors.left: choose3.left
activeFocusOnPress: true
style:radioStyle
property bool click : false //实现双击确定
onCheckedChanged: {
if(!this.checked) this.click=0;
}
onClicked: {
if(this.click){
result.text=this.text;
resultHolder.visible=true;
this.click=false;
}
else this.click=true;
}
Keys.enabled: true
Keys.onReturnPressed: {
result.text=this.text;
resultHolder.visible=true;
}
Keys.onEscapePressed: {
resultHolder.visible=false;
}
KeyNavigation.up: choose3
KeyNavigation.down: choose1
}
}
}
6.CheckBox
多选。
用CheckBoxStyle设置样式。
7.GroupBox
多选,外面加个边框。
title:标题
checkable:true 标题可选
flat:true 去掉边框
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
color:"white"
Rectangle{
id:resultHolder
color:"#a0a0a0"
width:200
height:100
anchors.centerIn: parent
visible: false
z:2
opacity: 0.8
border.width: 2
border.color: "#808080"
radius: 8
Text{
id:result
anchors.fill: parent
anchors.margins:5
font.pointSize: 16
color:"blue"
font.bold: true
wrapMode: Text.WordWrap
}
}
Component{
id:checkStyle
CheckBoxStyle{
indicator: Rectangle{
implicitHeight: 14
implicitWidth: 14
border.color: control.hovered ? "darkblue" : "gray"
border.width:1
Canvas{ //画布,详见下一章
anchors.fill: parent
anchors.margins: 3
visible:control.checked
onPaint:{
var ctx=getContext("2d");
ctx.save();
ctx.strokeStyle="#C00020"
ctx.lineWidth=2;
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(width,height);
ctx.moveTo(0,height);
ctx.lineTo(width,0);
ctx.stroke();
ctx.restore();
}
}
}
label: Text{
color:control.checked?"blue":"black"
text:control.text
}
}
}
GroupBox{
id:groupbox
checkable: true
title:"请选择你喜欢的文字游戏(们):"
anchors.top:parent.top
anchors.topMargin:8
anchors.left: parent.left
anchors.leftMargin: 20
width:280
height:160
Column{
id:games
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 5
spacing: 8
CheckBox{
text:"潜伏之赤途"
style:checkStyle
onClicked: resultHolder.visible = false;
}
CheckBox{
text:"中心少女"
style:checkStyle
onClicked: resultHolder.visible = false;
}
CheckBox{
text:"刻痕"
style:checkStyle
onClicked: resultHolder.visible = false;
}
CheckBox{
id:checkbox4
text:"恒水中学连环虐杀"
style:checkStyle
onClicked: resultHolder.visible = false;
}
}
Button{
id:confirm
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
text:"确定"
onClicked: {
var str=new Array();
var index=0;
var count=games.children.length;
for(var i=0;i<count;i++){
if(games.children[i].checked){
str[index++]=games.children[i].text;
}
}
if(index>0){
result.text=str.join();
resultHolder.visible=true;
}
}
}
}
}
}
8.ComboBox
下拉菜单。
用model:[字符串数组] 表示下拉选择的内容。
currentText表示当前选中的内容,currentIndex表示其数组序号。
9.ProgressBar
进度条。
minimumValue:最小值
maximumValue:最大值
value:当前值
orientation:Qt.Horizontal水平方向,Qt.Vertical垂直方向。
给进度条加百分比:不能只重写ProgressBarStyle里面的panel,否则进度条无法显示!必须重新载入background和progress。
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
color:"white"
ProgressBar{
id:bar
minimumValue: 0
maximumValue: 100
value: 0
width: 150
height: 20
z:1
anchors.centerIn: parent
style: ProgressBarStyle{
id:progressbarstyle
background: Rectangle{
border.width: 1
border.color: control.hovered? "green":"gray"
color:"lightgray"
}
progress: Rectangle{
color:"#208020"
}
panel: Item{
implicitWidth: 200
implicitHeight: 20
Loader{
anchors.fill: parent
sourceComponent: background
}
Loader{
id:progressLoader
anchors.top:parent.top
anchors.left: parent.left
anchors.bottom: parent.bottom
anchors.margins: 3
z:1
width:currentProgress*(parent.width-6)
sourceComponent:progressbarstyle.progress
}
Text{
color:"blue"
text:currentProgress*100+"%"
z:2
anchors.centerIn: parent
}
}
}
Timer{
interval:1000
repeat: true
running: true
onTriggered: {
if(parent.value<99.9){
parent.value+=10;
}
else{
restart();
parent.value=0;
}
}
}
}
}
}
10.TabView
标签页。
count:标签页的总数。
currentIndex:标签页的序号,从0开始。
tabVisible:默认在顶部,Qt.BottomEdge在底部。
addTab(title,component):增添一个以title为标题,以component控件为内容的标签页。
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
height:640
width:480
visible:true
Rectangle{
anchors.fill: parent
color:"white"
Component{
id:tabContent
Rectangle{
implicitWidth: 100
implicitHeight: 100
anchors.fill: parent
color: Qt.rgba(Math.random(),Math.random(),Math.random(),1)
}
}
TabView{
id:tabView
anchors.top: parent.top
anchors.margins: 8
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
tabPosition: Qt.BottomEdge
Component.onCompleted: {
for(var i=0;i<5;i++){
tabView.addTab("tab-"+i,tabContent);
}
}
}
}
}
11.Slider
滑块。
minimumValue:设置最小值,默认为0。
maximumValue:设置最大值,默认为1。
value:当前值,默认为0
onValueChanged:当前值改变时,处理信号。
stepSize:步长。
Column{
width:200
spacing:16
Text{
id:sliderStat
color:"blue"
text:"current-0.1"
}
Slider{
width:200
height:30
stepSize:0.01
value:0.1
onValueChanged: {
sliderStat.text="current-"+value;
}
}
}
}
12.Flickable
可拖拽组件。
Window {
height:200
width:200
visible:true
visibility:Window.Maximized
Flickable {
anchors.fill: parent
contentWidth: image.width; contentHeight: image.height
Image { id: image; source: "file:///C:/Users/doujihu/Pictures/water.jpg" }
}
}
七、Canvas
画布。
Canvas{
anchors.fill: parent
onPaint:{
var ctx=getContext("2d");
}
}
lineWidth:画笔粗细
strokeStyle:画笔颜色
fillStyle:填充颜色
beginPath():开始绘制路径。
moveTo(x,y):将路径点从纸上拿起来,移动到(x,y)。
lineTo(x,y):从当前点到(x,y)连一条直线路径,但是不涂色。
closePath():将路径终点与起点相连,绘制一条封闭路径。
stroke():将当前路径用strokeStyle涂色。
fill():若当前路径闭合,则用fillStyle填充颜色。
rect(x1,x2,y1,y2):绘制矩形路径。
arc(x,y,r,start,end,anticlockwise=1):以(x,y)为圆心,r为半径,从start到end画弧路径,anticlockwise表示是否逆时针。
createLinearGradient(x1,y1,x2,y2):返回一个从(x1,y1)到(x2,y2)的线性渐变对象gradient。用gradient.addColorStop(0~1,颜色)来设置渐变色的边界点。
Window {
width:400
height:240
visible:true
Canvas{
anchors.fill: parent
onPaint:{
var ctx=getContext("2d");
ctx.lineWidth=2;
ctx.strokeStyle="red";
var gradient=ctx.createLinearGradient(60,50,180,130);
gradient.addColorStop(0.0,Qt.rgba(1,0,0,1));
gradient.addColorStop(1.0,Qt.rgba(0,0,0,1));
ctx.fillStyle=gradient;
ctx.beginPath();
ctx.arc(100,100,50,0,2*Math.PI,1);
ctx.fill();
ctx.stroke();
}
}
}
绘制文字:
text("string",x,y):建立文字路径。
fillText(),strokeText():填充文字和描边。
设置字体:ctx.font="42px fantasy" 42像素大小,fantasy字体。
绘制图片:
drawImage(image,x,y):在(x,y)处绘制image(可以是Image元素或url)。
当图片加载完成时,才能绘制图片:(放在onPaint下面)
Component.onCompleted: loadImage(source);
onImageLoaded: requestPaint();
可以利用这个来实现快速切换图片。
注意要清空画布,否则原来的图片不会消失。
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
width:1024
height:768
visibility: Window.Maximized
visible:true
Canvas{
id:root
anchors.fill: parent
property string source: "file:///C:/Users/doujihu/Desktop/其他/素材/1.jpg"
onPaint:{
var ctx=getContext("2d");
ctx.save();
ctx.clearRect(0,0,root.width,root.height);
ctx.beginPath();
ctx.translate(400,0);
ctx.rotate(Math.PI/4);
ctx.drawImage(source,0,0);
ctx.restore();
}
Component.onCompleted: loadImage(source);
onSourceChanged: loadImage(source);
onImageLoaded: requestPaint();
MouseArea{
anchors.fill: parent
onClicked:{
root.source="file:///C:/Users/doujihu/Desktop/其他/素材/2.png"
}
}
}
}
图形变换:
变换前要ctx.save(),变换后要ctx.restore()。
translate(x,y):将画布中心从(0,0)平移到(x,y)。
rotate(rad):顺时针旋转rad弧度。
scale(x,y):横向缩放x倍,纵向缩放y倍。
clip():裁剪已有路径的内部。
先绘制路径,再调用clip(),最后再调用drawImage()。
八、动画
1.PropertyAnimation
通过改变对象的property实现动画。
有3种方法:(1)单独声明一个PropertyAnimation对象,在信号处理时调用animation.start()。(2)on<Signal>:PropertyAnimation+大括号,表示收到信号时开始运行动画。(3)在目标对象内部用Animation on <property>+大括号:将PropertyAnimation与一个属性绑定,然后设置running:触发属性的条件。
targets:目标对象 可以是[obj1,obj2,...]的数组,也可以是一个对象。
properties:"width,height" 对象的属性,多个属性用逗号隔开
to:多个属性共用的同一个目标值。
duration:持续时间(ms)。
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
width:360
height:240
visible: true
Rectangle{
id:rootItem
anchors.fill: parent
color:"#EEEEEE"
Rectangle{
id:rect
width:50
height:150
anchors.centerIn: parent
color:"blue"
MouseArea{
id:mousearea
anchors.fill: parent
onClicked:{
animation.start();
}
}
PropertyAnimation on width{
id:animation
to:150
duration:1000
running:false
}
}
}
}
animation.running:true/animation.start() 开始运行动画
onStarted和onStopped为开始和结束信号,用一个var保存当前的状态,可以实现动画反复运行。
Window {
width:360
height:240
visible: true
Rectangle{
id:rootItem
anchors.fill: parent
color:"#EEEEEE"
Rectangle{
id:rect
width:50
height:150
anchors.centerIn: parent
color:"blue"
property var animation;
PropertyAnimation{
id:toSquare
target:rect
property:"width"
to:150
duration: 1000
onStarted: {
rect.animation=toSquare;
rect.color="red";
}
onStopped: {
rect.color="blue";
}
}
PropertyAnimation{
id:toRect
target:rect
property:"width"
to:50
duration: 1000
onStarted: {
rect.animation=toRect;
rect.color="red";
}
onStopped: {
rect.color="blue";
}
}
MouseArea{
anchors.fill: parent
onClicked:{
if(rect.animation===toRect||rect.animation===undefined){
toSquare.start();
}
else{
toRect.start();
}
}
}
}
}
}
easing.type:动画速度变化模型。默认为Easing.Linear。
NumberAnimation,RotationAnimation,ColorAnimation为专用的动画处理器。
2.PathAnimation
让目标对象沿着一个既定的路径运动。
anchorPoint:"x,y" 对象初始位置
orientationEntryDuration:将对象调整到初始方向所用的时间
orientationExitDuration:将对象调整到设定的终止方向(endRotation)所用的时间
orientation:控制目标对象沿路径运动时的旋转策略。默认值为PathAnimation.Fixed保持物体方位不旋转。TopFirst表示目标顶部贴合路径。
path:Path对象。
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
width:400
height:240
visible: true
Canvas{
anchors.fill:parent
onPaint:{
var ctx=getContext("2d");
ctx.lineWidth=4;
ctx.strokeStyle="red";
ctx.beginPath();
ctx.arc(200,0,160,Math.PI*2,0,false);
ctx.stroke();
}
Rectangle{
id:rect
width:40
height:40
color:"blue"
x:20
y:0
MouseArea{
anchors.fill: parent
id:mouseArea
onClicked: pathAnim.start();
}
PathAnimation{
id:pathAnim
target:rect
duration:6000
anchorPoint: "20,20"
orientationEntryDuration: 200
orientationExitDuration: 200
easing.type: Easing.InOutCubic
orientation:PathAnimation.TopFirst;
path: Path{
startX:40
startY:0
PathArc{
x:360
y:0
useLargeArc: true
radiusX: 160
radiusY: 160
direction: PathArc.Counterclockwise;
}
}
}
}
}
}
3.ParallelAnimation
并行播放动画。
loops:循环方式。数字表示循环几次,Animation.Infinite表示无限循环。
animation.pause()表示暂停,此时animation.paused置1,running置0。可以通过anim.resume()恢复。
onClicked: {
if(anim.paused) anim.resume();
else if(anim.running) anim.pause();
else anim.start();
}
4.SequentialAnimation
顺序播放动画。
5.State
把几个属性绑成一个状态。
states: [State1,State2,...]:状态列表。
State{name:"string",when:表达式,changes:[PropertyChanges,AnchorsChanges等]}
when:当表达式为true时,触发状态变化。也可以用XXX.state="name"。
explicit:true:只变化一次,false将changes绑定。
6.StateChangeScript和ScriptAction
当状态改变\调用start()时,执行script:后面的代码。
name:"name"表示script的名字,可以被ScriptAction对象引用。
这样虽然逻辑上更直接,但是没法插入动画。
利用状态转移修改属性:
Window {
width:360
height:240
visible: true
Rectangle{
id:rootItem
color:"#EEEEEE"
anchors.fill: parent
Rectangle{
id:rect
color:"blue"
width:200
height:200
anchors.centerIn: parent
MouseArea{
id:mouseArea
anchors.fill: parent
onClicked:{
rect.state="resetWidth"
}
}
states:[
State{
name:"resetWidth"
StateChangeScript{
script:{
rect.color="red";
rect.width=rootItem.width;
}
}
}
]
}
}
}
等效于:
Window {
width:360
height:240
visible: true
Rectangle{
id:rootItem
color:"#EEEEEE"
anchors.fill: parent
Rectangle{
id:rect
color:"blue"
width:200
height:200
anchors.centerIn: parent
MouseArea{
id:mouseArea
anchors.fill: parent
onClicked:{
action1.start();
}
}
ScriptAction{
id:action1
script:{
rect.color="red";
rect.width=rootItem.width;
}
}
}
}
}
7.Transition
两个状态之间的过渡动画。
Item的transitions属性是个列表,保存Item定义的所有Transition。
scale:缩放系数。
与state对应的动画不用写target和from to。
对于并行动画,可以直接放在大括号内,对于顺序动画,必须加SequentitalAnimation并置reversible为true。
Window {
width:360
height:240
visible: true
Rectangle{
id:rootItem
color:"#EEEEEE"
anchors.fill: parent
Rectangle{
id:rect
color:"gray"
width:50
height:50
anchors.centerIn: parent
MouseArea{
id:mouseArea
anchors.fill: parent
}
states:State{
name:"pressed"
when:mouseArea.pressed
PropertyChanges {
target: rect
color:"green"
scale:2.0
}
}
transitions: Transition {
NumberAnimation{
property: "scale"
easing.type: Easing.InOutQuad
duration:1000
}
ColorAnimation { duration: 600 }
}
}
}
}
8.Behavior
给property绑定动画,当property改变时自动播放动画。
一个Behavior内只能有一个顶层动画。
Window {
width:360
height:240
visible: true
Rectangle{
id:rootItem
color:"#EEEEEE"
anchors.fill: parent
Rectangle{
id:rect
color:"yellow"
width:100
height:100
anchors.centerIn: parent
MouseArea{
id:mouseArea
anchors.fill: parent
onClicked:{
text1.opacity=0;
text1.text="bye!";
}
}
Text{
id:text1
color:"blue"
anchors.centerIn: parent
font.bold: true
font.pixelSize: 24
text:"hello world!"
Behavior on text{
PropertyAnimation{
duration:500
}
}
Behavior on opacity{
SequentialAnimation{
NumberAnimation{
id:anim1
from:1
to:0
duration:500
}
NumberAnimation{
id:anim2
from:0
to:1
duration:500
}
}
}
}
}
}
}
一个完整的对话框实现:
import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.2
Window {
width:360
height:240
visible: true
visibility: Window.Maximized
Rectangle{
id:rootItem
color:"#EEEEEE"
anchors.fill: parent
Rectangle{
id:rect
color:Qt.rgba(0,0,1,0.2);
width:parent.width
height:parent.height/4
anchors.bottom: parent.bottom
property string str: "一个人的一生应该是这样度过的:当他回首往事的时候,他不会因为虚度年华而悔恨,也不会因为碌碌无为而羞耻;这样,在临死的时候,他就能够说:“我的整个生命和全部精力,都已经献给世界上最壮丽的事业——为人类的解放而斗争。”"
property int index:0
MouseArea{
id:mouseArea
anchors.fill: parent
onClicked:{
if(rect.index<rect.str.length-1){
anim.start();
}
}
onDoubleClicked: {
var temp=rect.index;
rect.index=rect.str.length-1;
text1.text=rect.str;
anim.stop();
}
}
Text{
id:text1
anchors.top:parent.top
anchors.margins: 20
anchors.left: parent.left
height:parent.height-20
width:parent.width-20
opacity: 1
color:"black"
font.pixelSize: 24
font.bold: true
font.family: "楷体"
wrapMode:Text.WrapAnywhere
PropertyAnimation on text{
id:anim
to:text1.text+rect.str[rect.index]
duration:100
running:false
onStopped: {
if(rect.index<rect.str.length-1){
rect.index++;
anim.start();
}
}
}
}
}
}
}