知識點:
自定義按鈕:

import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Button { id:btn x: 0 y: 62 text: "Quit2" style:ButtonStyle { background: Rectangle { implicitWidth: 100 implicitHeight: 25 border.width: btn.pressed ? 2 : 1 } } } }
多個窗口:

import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 1.4 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Button { // 會默認放到 data 列表中 id:btn text: "Quit" } Window { id: root2 visible: true title: qsTr("Hello World") width: 300 height: 100 flags: Qt.Popup Text{ text: "Hello Qt Quick" } } }
顏色 LinearGradient :

import QtQuick 2.12 import QtQuick.Window 2.12 import QtGraphicalEffects 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ width: 500 height: 500 border.color: Qt.lighter("purple") border.width: 2 radius: 15 LinearGradient { anchors.fill: parent start: Qt.point(0, 0) end: Qt.point(500, 500) gradient: Gradient { GradientStop { position: 0.000 color: Qt.rgba(1, 0, 0, 1) } GradientStop { position: 0.167 color: Qt.rgba(1, 1, 0, 1) } GradientStop { position: 0.333 color: Qt.rgba(0, 1, 0, 1) } GradientStop { position: 0.500 color: Qt.rgba(0, 1, 1, 1) } GradientStop { position: 0.667 color: Qt.rgba(0, 0, 1, 1) } GradientStop { position: 0.833 color: Qt.rgba(1, 0, 1, 1) } GradientStop { position: 1.000 color: Qt.rgba(1, 0, 0, 1) } } source: Image { source:"images/ufo.png" } } Component.onCompleted: { console.log(color.r,color.g,color.b,color.a); } } }
Text 控件 多余文字顯示 三個點:

import QtQuick 2.12 import QtQuick.Window 2.12 import QtGraphicalEffects 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 color: "cyan" Rectangle{ id:rect1 color: "purple" width: 150 height: 100 Text { id: txt1 anchors.fill:parent text: qsTr("<h1>Hello Red Text,Hello Red Text,Hello Red Text,Hello Red Tex</h1>") color:"red" clip: true wrapMode: Text.WrapAnywhere elide: Text.ElideRight } } }
Image 相關:
顯示GIF 圖片:
Image不能顯示GIF,因為Image只能顯示靜態圖片,可以使用 AnimatedImage 顯示動態圖片

import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 color: "cyan" Image { id: img1 width: 100 height: 100 source: "images/1.gif" // 不能顯示GIF,因為Image只能顯示靜態圖片 } // 可以使用 AnimatedImage 顯示動態圖片 AnimatedImage { id:aniImg1 x:100 y:100 width: 100 height: 100 source: "images/1.gif" } }
異步加載網絡圖片:
使用了 BusyIndicator 組件

import QtQuick 2.12 import QtQuick.Window 2.12 import QtQuick.Controls 2.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 color: "cyan" Rectangle{ width: 500 height: 500 border.color: "red" border.width: 2 BusyIndicator{ id:loading running: true anchors.centerIn: parent z:2 // z-index } Text { id: desc visible: false anchors.centerIn: parent z:3 // z-index } Image { id: img1 cache: false // 在加載大型圖片一般不要進行緩存 anchors.fill: parent source: "http://pic1.juimg.com/161122/330846-16112222051832-lp.jpg" fillMode: Image.PreserveAspectFit asynchronous: true // 開啟異步加載 圖片 網絡資源自動就是異步,本地資源默認都是同步 onStatusChanged: { if(img1.status === Image.Loading){ loading.running = true; desc.visible = false; // console.log("loading"); }else if(img1.status === Image.Ready){ loading.running = false; // console.log("ready"); }else if(img1.status === Image.Error){ loading.running = true; desc.visible = true; desc.text = "load img error"; // console.log("error"); } } // focus: true // Keys.onPressed: { // if(event.key === Qt.Key_A){ // console.log(img1.status,"|||| ",Image.Error); // } // } } } }
效果:
圖片查看器(一次打開單張圖片):

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 minimumWidth: 480 minimumHeight: 360 BusyIndicator{ id:loading running: false anchors.centerIn: parent z:2 } Text { id: stateTxt visible: false anchors.centerIn: parent z:3 } Image { id: imageViewer asynchronous: true // 異步加載 cache: false // 關閉緩存 anchors.fill: parent fillMode: Image.PreserveAspectFit onStatusChanged: { if(imageViewer.status === Image.Loading){ loading.running = true; stateTxt.visible = false; }else if(imageViewer.status === Image.Ready){ loading.running = false; }else if(imageViewer.status === Image.Error){ loading.running = true; stateTxt.visible = true; stateTxt.text = "load image error"; } } } Button{ id:openFile text: "Open" anchors.left: parent.left anchors.leftMargin: 8 anchors.bottom: parent.bottom anchors.bottomMargin: 8 onClicked:fileDialog.open() } FileDialog{ id:fileDialog title: "Please choose a file" nameFilters: ["Image Files (*.jpg *.png *.gif)"] onAccepted: { imageViewer.source = fileDialog.fileUrl; var imageFile =new String(fileDialog.fileUrl); imagePath.text = imageFile.slice(8); } } Text { id: imagePath anchors.left: openFile.right anchors.leftMargin: 8 anchors.verticalCenter: openFile.verticalCenter font.pixelSize: 18 } }

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 minimumWidth: 480 minimumHeight: 360 BusyIndicator{ id:loading running: false anchors.centerIn: parent z:2 } Text { id: stateTxt visible: false anchors.centerIn: parent z:3 } Image { id: imageViewer asynchronous: true // 異步加載 cache: false // 關閉緩存 anchors.fill: parent fillMode: Image.PreserveAspectFit onStatusChanged: { if(imageViewer.status === Image.Loading){ loading.running = true; stateTxt.visible = false; }else if(imageViewer.status === Image.Ready){ loading.running = false; }else if(imageViewer.status === Image.Error){ loading.running = true; stateTxt.visible = true; stateTxt.text = "load image error"; } } } Button{ id:openFile text: "Open" anchors.left: parent.left anchors.leftMargin: 8 anchors.bottom: parent.bottom anchors.bottomMargin: 8 onClicked:fileDialog.open() } FileDialog{ id:fileDialog title: "Please choose a file" nameFilters: ["Image Files (*.jpg *.png *.gif)","Bitmap Files (*.bmp)","* (*.*)"] selectedNameFilter:"Image Files (*.jpg *.png *.gif)" // 默認過濾器 selectMultiple: true // 選擇多個文件 onAccepted: { imageViewer.source = fileDialog.fileUrls[0]; var imageFile =new String(fileDialog.fileUrl[0]); imagePath.text = imageFile.slice(8); } } Text { id: imagePath anchors.left: openFile.right anchors.leftMargin: 8 anchors.verticalCenter: openFile.verticalCenter font.pixelSize: 18 } }
Loader:
Loader 用來動態加載QML Component 組件,

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Loader{ id:redLoader anchors.left: parent.left anchors.leftMargin: 4 anchors.bottom: parent.bottom anchors.bottomMargin: 4 sourceComponent: colorComponent onLoaded: { item.color = "red"; // 這里的item 指的是 所加載的頂層對象即 rect } } Component{ id:colorComponent // 注Component 中只能有一個id 屬性 和 一個頂層對象!!! Rectangle{ id:rect width: 50 height: 50 signal zcb(color clr) MouseArea{ anchors.fill: parent onPressed: rect.zcb(rect.color) } onZcb:{ rect.color = "yellow"; } } } }
如果Loader加載的Item 想要處理按鍵事件,必須要把Loader 中的 focus 設置為true

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Loader{ id:redLoader anchors.left: parent.left anchors.leftMargin: 4 anchors.bottom: parent.bottom anchors.bottomMargin: 4 sourceComponent: colorComponent onLoaded: { item.color = "red"; } // 如果Loader加載的Item 想要處理按鍵事件,必須要把Loader focus 設置為true,這樣它所加載的組件才可以接收到focus focus: true // 開啟按鍵事件 } Component{ id:colorComponent Rectangle{ id:rect width: 50 height: 50 signal zcb(color clr) MouseArea{ anchors.fill: parent onPressed: rect.zcb(rect.color) } onZcb:{ rect.color = "yellow"; } focus: true Keys.onPressed: { console.log(event.key); event.accepted = true; } } } }
從文件中加載組件:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Loader{ id:redLoader anchors.left: parent.left anchors.leftMargin: 4 anchors.bottom: parent.bottom anchors.bottomMargin: 4 // sourceComponent: colorComponent source: "MyTest.qml" onLoaded: { console.log(item); //此時 item 仍然是頂層對象 item.color = "red"; } // 如果Loader加載的Item 想要處理按鍵事件,必須要把Loader focus 設置為true,這樣它所加載的組件才可以接收到focus focus: true // 開啟按鍵事件 } }

import QtQuick 2.10 Rectangle{ id:colorComponent width: 50 height: 50 signal zcb(color clr) MouseArea{ anchors.fill: parent onPressed: colorComponent.zcb(colorComponent.color) } onZcb:{ colorComponent.color = "yellow"; } focus:true Keys.onPressed: { console.log(event.key); event.accepted = true; } }
動態創建和銷毀控件:
利用Loader,可以通過設置source為 空串,設置sourceComponent 為undefined 可以銷毀控件 ~
在js 中動態創建組件對象:
有兩種方式:
1,使用Qt.createComponent() 動態創建一個組件對象,然后使用Component 的createObject() 創建它的實例對象。
2,使用Qt.createQmlObject() 從一個QML字符串直接創建一個實例對象
注:
如果已經有一個QML文件中定義了一個組件,你想創建它的實例對象,這時使用1較好。
如果QML對象本身是在運行時產生的,那么Qt.createQmlObject() 可能是比較好的選擇。
第一種,

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect anchors.fill: parent focus: true Keys.onPressed: { if(event.key === Qt.Key_A){ // 創建組件對象 var newCom = Qt.createComponent("MyTest.qml"); newCom.createObject(rect,{"color":"cyan"});// 第一個參數為父級,后面是新創建組件的屬性 } } } }

import QtQuick 2.10 Rectangle{ id:colorComponent width: 50 height: 50 signal zcb(color clr) MouseArea{ anchors.fill: parent onPressed: colorComponent.zcb(colorComponent.color) } onZcb:{ colorComponent.color = "yellow"; } focus:true Keys.onPressed: { console.log(event.key); event.accepted = true; } }
第二種,

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect anchors.fill: parent focus: true Keys.onPressed: { if(event.key === Qt.Key_A){ // 創建組件對象 var newCom = Qt.createQmlObject('import QtQuick 2.0; Rectangle {color: "red"; width: 20; height: 20;}', rect, "newCom01"); // 第三個參數 是給對象關聯一個文件路徑,主要用於報告錯誤 } } } }
銷毀動態創建的對象:
這里說的銷毀不是僅僅把對象的visible 設為false或者是opacity 設置為0 。
需要調用 destroy() 函數,

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Controls 2.10 import QtQuick.Dialogs 1.3 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect anchors.fill: parent property var mycom: null focus: true Keys.onPressed: { if(event.key === Qt.Key_A){ // 創建組件對象 rect.mycom = Qt.createQmlObject('import QtQuick 2.0; Rectangle {color: "red"; width: 20; height: 20;}', rect, "newCom01"); // 第三個參數 是給對象關聯一個文件路徑,主要用於報告錯誤 } if(event.key === Qt.Key_B){ console.log(rect.mycom); rect.mycom.destroy(0); // 0s 后銷毀 } } } }
點擊a 創建,點擊b 銷毀~
Qt Quick 元素布局:
三大類:
1,前面說過的 錨布局(Anchor),它是利用Item 的anchors 屬性實現,非常方便!!!
2,定位器(Position),它包含了Row(行定位器),Column(列定位器),Grid(表格定位器),Flow(流定位器)
3,布局管理器(Layout),它包含 行布局(RowLayout),列布局(ColumnLayout),表格布局(GridLayout)
定位器Position
略
布局管理器Layout
Qml 的布局管理器和 Qt widgets 相似,它與定位器的不同之處在於:布局管理器會自動調整子Item 的尺寸來適應界面大小的變化。
要使用布局管理器,需要引入Layouts 模塊。
GridLayout:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rootItem width: 360 height: 240 color:"#eee" GridLayout{ width: 200 anchors.left: parent.left anchors.leftMargin: 4 anchors.top: parent.top anchors.topMargin: 4 rows:2 columns: 2 rowSpacing: 4 columnSpacing: 4 Rectangle{ id:rect1 width:100 height: 100 color: "purple" Layout.columnSpan: 2 Layout.rowSpan: 2 Layout.fillWidth: true } Rectangle{ id:rect2 width:100 height: 100 color: "cyan" } Rectangle{ id:rect3 width:100 height: 100 color: "yellow" } } } }
RowLayout

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rootItem width: 400 height: 240 color:"#eee" RowLayout{ width: 400 anchors.left: parent.left anchors.leftMargin: 4 anchors.top: parent.top anchors.topMargin: 4 Rectangle{ id:rect1 width:100 height: 100 color: "purple" } Rectangle{ id:rect2 width:100 height: 100 color: "cyan" } Rectangle{ id:rect3 width:100 height: 100 color: "yellow" Layout.fillWidth: true } } } }
ColumnLayout:
類似...
QML 常用控件:
1,行編輯:
TextInput ,TextField
2,文本塊:
TextEdit,TextArea
3,互斥分組:
ExclusiveGroup
4,RadioButton:
單選按鈕
5,CheckBox:
多選框
6,GroupBox:
分組框
7,ComboBox:
下拉框
8,ProgressBar:
進度條
9,TabView:
點擊標簽會進入對應界面,選項卡控件
10,Slider:
滑塊控件
11,Flickable:
Flickable提供一個較小的視窗來顯示一個較大的內容給用戶,並且用戶可以對改內容進行拖拽和輕拂
12,Screen:
它是顯示Item 的那個屏幕,它提供了一些只讀屬性來描述屏幕參數。
Canvas 畫布:
Canvas 是Item 的派生類,
1,畫布:

Canvas{ width: 300 height: 200 }
這即是一塊畫布,
2,畫師:
畫師是Context2D ,QT幫助文檔直接搜索Context2D ,

Canvas{ width: 300 height: 200 onPaint: { var ctx = getContext("2d"); // 在QML 中,一塊畫布只有一個畫師 } }
3,畫筆:
關於畫筆的屬性設置,在Contex2D對象 上都有,有筆的粗細(lineWidth),筆的顏色(strokeStyle)之類的
4,畫刷:
畫刷是用來填充畫筆勾勒出的區域的,屬性是fillStyle,
坐標系:
在2D世界,原點位於屏幕左上角(0,0), 向右是x 軸,向下是y軸。
圖元:
基本的圖元有線,弧,矩形,曲線,文本,圖片,
小試牛刀:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ width: 800 height: 600 onPaint: { var ctx = getContext("2d"); // 在QML 中,一塊畫布只有一個畫師 ctx.lineWidth = 2; ctx.strokeStyle = "red"; // 畫筆顏色 ctx.fillStyle = "blue"; // 畫刷 顏色 ctx.beginPath(); ctx.rect(60,50,120,80); ctx.fill(); ctx.stroke(); // 使用stroke() 結束路徑的繪制 var gradient = ctx.createRadialGradient(200,140,40,280,220,20); gradient.addColorStop(0.0,Qt.rgba(1,0,0,1.0)); gradient.addColorStop(1.0,Qt.rgba(0,0,1,1.0)); ctx.fillStyle = gradient; ctx.beginPath(); ctx.rect(200,140,80,80); ctx.fill(); ctx.stroke(); } } }

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ width: 800 height: 600 onPaint: { var ctx = getContext("2d"); // 在QML 中,一塊畫布只有一個畫師 ctx.lineWidth = 2; ctx.strokeStyle = "red"; // 畫筆顏色 ctx.fillStyle = "blue"; // 畫刷 顏色 ctx.beginPath(); ctx.moveTo(100,80); // 移動到 100,80 ctx.lineTo(100,200); // 從當前位置到(x,y)點繪制一條直線 ctx.lineTo(300,200); ctx.closePath(); // 結束當前的路徑,從路徑終點到起點繪制一條直線來封閉路徑 ctx.fill(); ctx.stroke(); // 使用stroke() 結束路徑的繪制 } } }

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ width: 800 height: 600 onPaint: { var ctx = getContext("2d"); // 在QML 中,一塊畫布只有一個畫師 ctx.lineWidth = 2; ctx.strokeStyle = "red"; // 畫筆顏色 ctx.fillStyle = "blue"; // 畫刷 顏色 ctx.font = "42px sans-serif"; ctx.beginPath(); ctx.moveTo(4,4); ctx.bezierCurveTo(0,height - 1,width -1 ,height/2,width/4,height/4); ctx.lineTo(width/2,height/4); ctx.arc(width*5/8,height/4,width/8,Math.PI,0,false); ctx.ellipse(width*11/16,height/4,width/8,height/4); ctx.lineTo(width/2,height*7/8); ctx.text("Hello World",width/4,height*7/8); ctx.fill(); ctx.stroke(); // 使用stroke() 結束路徑的繪制 } } }
與文本相關:
有三個方法:fillText() ,strokeText(),text()

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ width: 800 height: 600 onPaint: { var ctx = getContext("2d"); // 在QML 中,一塊畫布只有一個畫師 ctx.lineWidth = 2; ctx.strokeStyle = "red"; // 畫筆顏色 ctx.font = "42px sans-serif"; ctx.fillStyle = "green"; // 畫刷顏色 //1 ctx.beginPath(); ctx.text("Hello World -fill",50,50); ctx.fill(); //2 ctx.fillText("Hello World -fillText",50,150); //3 ctx.beginPath(); ctx.text("Hello World -stroke",50,200); ctx.stroke(); //4 ctx.strokeText("Hello World -strokeText",50,250); //5 ctx.beginPath(); ctx.text("Hello World -fill -stroke",50,300); ctx.fill(); ctx.stroke(); } } }
繪制圖片:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ width: 800 height: 600 property var imgSrc:"images/rocket.png" onPaint: { var ctx = getContext("2d"); //1 ctx.drawImage(imgSrc,100,100); } Component.onCompleted: loadImage(imgSrc); // loadImage 會異步加載圖片,當圖片加載完成時會發射imageLoaded 信號 onImageLoaded: { requestPaint(); // 重新繪制 Canvas 畫布 } } }
變換:
平移(translate),旋轉(rotate),縮放(scale),錯切(shear),

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ width: 800 height: 600 property var imgSrc:"images/rocket.png" onPaint: { var ctx = getContext("2d"); ctx.lineWidth = 2; ctx.strokeStyle = "blue"; ctx.fillStyle = "purple"; ctx.save(); ctx.beginPath(); ctx.translate(width/2,height/2); ctx.arc(0,0,30,0,Math.PI*2); ctx.arc(0,0,50,0,Math.PI*2); ctx.arc(0,0,70,0,Math.PI*2); ctx.arc(0,0,90,0,Math.PI*2); ctx.stroke(); ctx.restore(); // 恢復到save() 之前的狀態 ctx.save(); ctx.translate(width/2,30); ctx.font = "42px sans-serif"; ctx.textAlign="center"; ctx.fillText("concentric circles",0,0); ctx.restore(); } } }
Note :restore() 和 save()結合使用,
裁剪:
Context2D 的clip() 方法,讓我們能夠根據當前路徑包圍的區域來裁剪。

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ width: 800 height: 600 property var imgSrc:"images/1.jpg" onPaint: { var ctx = getContext("2d"); ctx.lineWidth = 2; ctx.strokeStyle = "blue"; ctx.fillStyle = Qt.rgba(0.3,0.5,0.7,0.3); ctx.save(); ctx.beginPath(); ctx.arc(180,150,80,0,Math.PI*2,true); ctx.closePath(); ctx.clip(); // 裁剪 ctx.drawImage(imgSrc,0,0); ctx.stroke(); ctx.fill(); ctx.rotate(Math.PI/5); ctx.font = "italic bold 32px serif"; ctx.fillStyle = "red"; // 字體填充顏色 ctx.fillText("Hello World,Wosdfjklf ",100,70); ctx.restore(); } Component.onCompleted: loadImage(imgSrc); onImageLoaded: requestPaint(); } }
圖像合成:
globalCompositeOperation
QML 動畫:
基本動畫對象:
PropertyAnimation: 通過改變各種類型的property 來產生動畫
NumberAnimation: PropertyAnimation 的子類,專門改變數字類型的property來產生動畫,效率比PropertyAnimation 好,
ColorAnimaiton : PropertyAnimation 的子類,專門改變color 類型的property 來產生動畫,效率比PropertyAnimation 好,
RotationAnimaiton : PropertyAnimation 的子類,專門改變rotation 值來產生動畫,效率比PropertyAnimation 好,另外還提供旋轉方向等附加屬性,
Vector3dAnimation: PropertyAnimation 的子類,當一個Vector3d值 發生變化時使用。
PathAnimation: 讓對象沿一個給定的方向移動
SmoothedAnimation: 允許一個property 跟蹤一個值,產生平滑動畫
SpringAnimation, 允許一個property 跟蹤一個值,動畫效果類似於彈簧運動,
分組動畫對象:
SequentialAnimation: 順序執行一系列動畫
ParallAnimation : 並行執行一系列動畫
動畫搭檔:
State,它是Item的狀態,不同狀態對應不同的界面效果和業務邏輯。
Transition, 過渡,它用來銜接不同狀態,使狀態變化過程平滑。
協同動畫元素:
Behavior : 它為Item 的property 變化綁定一個默認的動畫對象。
ParentAnimation, 當改變一個Item的parent的時候使用,使得從舊parent到新parent的過程更平滑,通常與State,Transition,ParentChange聯合使用。
AnchorAnimation: 當改變一個Item 的 anchor的時候使用,通常與State,Transition,AnchorChange聯合使用。
PauseAnimation:如果在動畫過程插入它,可以將動畫過程暫停一段時間。
PropertyAction: 動畫執行過程立即改變某個屬性。
ScriptAction:動畫執行過程運行一段JS腳本。
測試代碼:
PropertyAnimation定義的三種方式:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 50 height: 50 anchors.centerIn: parent color: "blue" MouseArea{ anchors.fill: parent onClicked: animation.running = true; } } Rectangle{ id:rect2 width: 50 height: 50 color: "red" } PropertyAnimation{ id:animation targets: [rect,rect2] properties: "width,height" to:150 duration: 1000; } }

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 50 height: 50 anchors.centerIn: parent color: "blue" MouseArea{ anchors.fill: parent onClicked: PropertyAnimation{ // 在信號處理器中直接使用動畫 id:animation target: rect properties: "width,height" to:150 duration: 1000; } } } }

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 50 height: 50 anchors.centerIn: parent color: "blue" MouseArea{ id:mouseArea anchors.fill: parent } PropertyAnimation on width{ // Animation on <property > 這種語法格式 可以將一個動畫和一個屬性關聯起來 to:150 duration: 1000 running: { return mouseArea.pressed } } } }
Animation 的started() 和 stopped() 信號:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 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{ id:mouseArea anchors.fill: parent onClicked: { if(rect.animation == toRect || rect.animation == undefined){ toSquare.start(); }else{ toRect.start(); } } } } }
NumberAnimation:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 50 height: 150 anchors.centerIn: parent color: "blue" NumberAnimation { id:numAni target: rect property: "width" to:150 duration: 200 easing.type: Easing.InOutQuad } MouseArea{ id:mouseArea anchors.fill: parent onClicked: { numAni.running = true; } } } }
ColorAnimation:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 50 height: 150 anchors.centerIn: parent color: "blue" MouseArea{ id:mouseArea anchors.fill: parent onClicked: ColorAnimation { target: rect property: "color" to: "green" duration: 200 } } } }
RotationAnimation:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 50 height: 150 anchors.centerIn: parent color: "blue" // transformOrigin: Item.TopRight Text { id: txt anchors.fill: parent text: qsTr("text") } MouseArea{ id:mouseArea anchors.fill: parent onClicked: RotationAnimation{ target: rect to:90 duration: 1000 direction: RotationAnimation.Clockwise // 順時針 } } } }
PathAnimation:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Canvas{ // 畫一個半圓 width: 400 height: 240 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{ id:mouseArea anchors.fill:parent onClicked: pathAnim.start(); } PathAnimation{ id:pathAnim target: rect duration: 6000 anchorPoint: "20,20"// rect 的center orientation: PathAnimation.BottomFirst orientationEntryDuration: 200 // 調整初始姿態的時間 endRotation: 0 // 最后的角度 :0 orientationExitDuration: 200 // 調整終止時姿態的時間 easing.type: Easing.InOutCubic path: Path{ startX: 40 startY: 0 PathArc{ x:360 // 終點(360,0) y:0 useLargeArc: true; // 采用 優弧(較大)模式 radiusX: 160 // 橢圓的兩個半軸 radiusY: 160 direction: PathArc.Counterclockwise // 逆時針 } } } } }
SmoothedAnimation:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 40 height: 40 color: "red" x:20 y:20 SmoothedAnimation{ // SmoothedAnimation默認采用 easing.type 為InOutQuad id:smoothAni1 target: rect property: "x" duration: 1000 velocity: -1 //速率 默認速率是200units/秒, -1 為禁用速率 // 如果duration和 velocity同時設置,那么會使用速率計算出一個時間, 它和duration的較短者會被采用。 } SmoothedAnimation{ id:smoothAni2 target: rect property: "y" velocity: 100 } } MouseArea{ anchors.fill: parent onClicked: { smoothAni1.from = rect.x; smoothAni1.to = mouse.x + 4; smoothAni1.start(); smoothAni2.from = rect.y; smoothAni2.to = mouse.y + 4; smoothAni2.start(); } } }
SpringAnimation:
可以用來模擬彈簧的震盪行為,

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 40 height: 40 color: "red" x:20 y:20 } SpringAnimation{ id:springAni1 target: rect property: "x" spring: 3 // 加速度 0-5 有意義 默認為0 damping: 0.06 //衰減系數0-1.0 有意義, 值越大會越快平復 epsilon: 0.25 //允許設定一個最接近0 的閾值代表0 ,如果是基於像素動畫,建議0.25 ,如果是基於scale動畫,建議0.005 。 默認為0.01 ,調整epsilon 可能會有一定的性能提升 } SpringAnimation{ id:springAni2 target: rect property: "y" spring: 3 damping: 0.06 epsilon: 0.25 } MouseArea{ anchors.fill: parent onClicked: { springAni1.from = rect.x; springAni1.to = mouse.x - 20; springAni1.start(); springAni2.from = rect.y; springAni2.to = mouse.y - 20; springAni2.start(); } } }
組合動畫:
略
State:
在QML中,狀態是定義在State類型中的一系列屬性配置。不同的配置可能有不同的作用:
1,顯示一些UI組件,隱藏另一些
2,想用戶呈現不同的操作和功能
3,啟動,暫停,停止動畫
4,在某種新的狀態下執行某些腳本
5,改變某個特定Item的property的值
6,顯示一個不同的view或screen
等等...
代碼:

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 360 height: 240 color: "#eee" Text { id: centerTxt text: qsTr("Just a text!") anchors.centerIn: parent font.pixelSize: 24 MouseArea{ id:mouseArea anchors.fill: parent onPressed: { centerTxt.state = "blueText"; } onReleased: { centerTxt.state = "redText"; } } state:"redText" states: [ State { name: "redText" changes: [ PropertyChanges { target: centerTxt color:"red" } ] }, State { name: "blueText" PropertyChanges { target: centerTxt color:"blue" } } ] } } }

import QtQuick 2.10 import QtQuick.Window 2.10 import QtQuick.Layouts 1.12 Window { id: root visible: true title: qsTr("Hello World") width: 800 height: 600 Rectangle{ id:rect width: 360 height: 240 color: "#eee" Text { id: centerTxt text: qsTr("Just a text!") anchors.centerIn: parent font.pixelSize: 24 MouseArea{ id:mouseArea anchors.fill: parent acceptedButtons: Qt.LeftButton | Qt.RightButton } state:"redText" states: [ State { name: "redText" when:mouseArea.pressedButtons === Qt.RightButton changes: [ PropertyChanges { target: centerTxt color:"red" }, PropertyChanges { target: centerTxt font.bold:true font.italic: true } ] }, State { name: "blueText" when: mouseArea.pressed PropertyChanges { target: centerTxt color:"blue" font.pixelSize: 48; } } ] } } }
C++ 與 QML 混合編程:
在QML中使用c++ 類和對象:
要想將一個類或對象導出到QML,前提條件是:
1,從QObject 或 QObject 的派生類繼承
2,使用Q_OBJECT 宏
省略...
在QML中使用c++ 類和對象: