(基于qt 5.3.1)
一、Qt Quick入門
1.啟動(dòng)Qt Quick App的兩種方式
窗口標(biāo)題、圖標(biāo)等由qml控制
main.cpp用QQmlApplicationEngine:
//main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])//主函數(shù)必須帶參
{
QGuiApplication app(argc, argv);//app的參數(shù)和main的參數(shù)對應(yīng)
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
}
}
窗口標(biāo)題、圖標(biāo)由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
}
}
注意:此處不能調(diào)用Qt.quit()。
2.Window對象
visibility:控制窗口最小化、最大化、全屏等。
直接在Window里面加入:
visibility: Window.Minimized
visibility: Window.Maximized
visibility: Window.FullScreen
color:"blue","#FFFFFF"
opacity:設(shè)置窗口透明度,取值范圍0~1
title:標(biāo)題
3.Rectangle:
color: Qt.rgba(r,g,b,a) ,rgba在0~1之間,rgb表示每種顏色所占的比例,a表示顏色的深淺。
gradient:漸變填充,優(yōu)先級高于color。每一個(gè)GradientStop為一個(gè)確定顏色的位置,在兩個(gè)確定顏色之間漸變填充。
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:旋轉(zhuǎn)角度,可以用rotation:90實(shí)現(xiàn)橫向漸變。
4.Item
Item是Rectangle的父類。
x,y:位置。
z:圖層的優(yōu)先級。z越大,越在其他圖層上面。
clip:在父類設(shè)定,默認(rèn)為false,當(dāng)設(shè)置為true時(shí)自動(dòng)調(diào)整子類的大小使之不會(huì)跑到父類外面去。
5.anchors
利用圖元之間的相對位置布局。
anchors.left:parent.left表示當(dāng)前圖元的最左側(cè)和它父類的最左側(cè)重合。
anchors.leftMargin:20表示當(dāng)前圖元的最左側(cè)向右移動(dòng)20像素。
anchors.fill:parent表示當(dāng)前圖元填滿它的父類。
anchors.centerIn:parent表示當(dāng)前圖元居中放置于它的父類中。
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
響應(yīng)鍵盤。
focus:焦點(diǎn),要讓某個(gè)元素響應(yīng)按鍵,必須把它的focus設(shè)成true。
Keys.enabled:鍵盤使能
Keys.onPressed:檢測到某個(gè)鍵被按下時(shí),就將event.key設(shè)成Qt.Keys_x,后者是宏,為那個(gè)鍵對應(yīng)的ASCII碼。
按某個(gè)數(shù)字鍵,就顯示某個(gè)數(shù)字的程序:(按Esc鍵退出)
注意:默認(rèn)為中文輸入法,要手動(dòng)切換。
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在兩個(gè)單詞之間換行,WrapAnywhere可以在單詞內(nèi)部換行。
font:字體設(shè)置,font.bold:true表示加粗,font.pixelSize:24表示一個(gè)字占24像素,font.underline:true表示下劃線。
text:文本內(nèi)容。
style:文字風(fēng)格,有Outline,Raised,Sunken等。
stylecolor:描邊的顏色。
font.family: "楷體" 設(shè)置字體
8.Button
需要引入import QtQuick.Controls 1.2
用onClicked表示按下按鈕后的操作。
這個(gè)操作相當(dāng)于c++代碼。
Button{
text:"Quit"
anchors.centerIn: parent
onClicked:{
Qt.quit();
}
}
checkable:設(shè)置Button是否可選。
iconSource:用URL的方式指定圖標(biāo)圖片。
focus:如果設(shè)置為true,則空格表示按下此按鈕。
style:設(shè)置按鈕的風(fēng)格。
style:ButtonStyle 有background,control和lable三個(gè)屬性,可以用于設(shè)置按鈕的背景,并隨操作而改變。
implicitWidth: 必須要加implicit。
implicitHeight:
control.pressed:是否按下按鈕
control.hovered:鼠標(biāo)是否懸停在按鈕上
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:照片的來源,可以是本地照片也可以是網(wǎng)絡(luò)照片,本地照片前要加"file:///"。
Window{
visible: true
height: 360
width: 480
Image{
anchors.fill: parent
source: "file:///C:/Users/doujihu/Desktop/其他/photos/照片.jpg"
}
}
默認(rèn)同步顯示圖片,要開啟異步設(shè)置:asynchronous: true
10.busyIndicator
等待的圓圈標(biāo)記。
running:true 顯示等待標(biāo)記
style:BusyIndicatorStyle{} 用于設(shè)置等待圖片。
11.FileDialog
需要引入import QtQuick.Dialogs 1.1
文件對話框,用于保存\打開文件。
id.open():彈出文件對話框
title:文件對話框的標(biāo)題
nameFilters:["Image Files(*.jpg *.png *.gif)"]
文件過濾器,只有這些后綴名的文件能被選中。
onAccepted:{}
選中后執(zhí)行的操作
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,一個(gè)變量可以賦值不同的數(shù)據(jù)類型。
語句后可以不寫分號,以換行作為結(jié)尾標(biāo)記。
原始類型:Undefined,Null,Boolean,Number,String,Object
typeof 運(yùn)算符:返回類型名
Undefined類型只有一個(gè)underfined值,表示未初始化的變量,沒有明確返回值的函數(shù),也返回undefined。
Null類型只有一個(gè)值null。
Boolean相當(dāng)于bool。
Number支持十六進(jìn)制,八進(jìn)制,科學(xué)記數(shù)法等。最大值為Number.MAX_VALUE,最小值為Number.MIN_VALUE。如果超過最大值,會(huì)返回Infinity,可以用isFinit()判斷是否有窮。NaN:表示強(qiáng)制類型轉(zhuǎn)換的對象不是純數(shù)字,只能用isNaN()判斷。
String字符串類型,沒有char。String類的變量是只讀的,不能通過S[0]='a'來修改。
Number.toString(base=10) 把數(shù)字以base為基轉(zhuǎn)化為字符串。
parseInt(String)和parseFloat(String) 從字符串的最左邊開始,到第一個(gè)非數(shù)字字符為止,提取數(shù)字。
Boolean() 對于非空對象,返回true,否則返回false。
Number() 對整個(gè)值轉(zhuǎn)換,如果整個(gè)值不是有效數(shù)字,返回NaN。
Object類:所有類的基類。
類成員可以動(dòng)態(tài)添加:
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(){ \\用等號聲明函數(shù)
console.log("name:",this.name,"\nyear:",this.year);
\\this的使用和c++一樣
}
person.show();
}
對象的屬性和方法可以用類似于map的下標(biāo)訪問。
console.log(person["name"]);
person["show"](); //相當(dāng)于person.show();
使用for...in...可以遍歷一個(gè)對象的屬性。
for(var i in person){
console.log(i,":",person[i]);
}
對象的字面量表示法:可以直接用大括號加冒號實(shí)例化類。
Window {
height:480
width:640
Component.onCompleted: {
var person = {
"name": "zhangsan",
"year": 20, //注意:兩個(gè)成員之間必須用逗號隔開
"show": function show(){
console.log(this.name,":",this.year);
}
}
person.show();
}
}
String類:
str.indexOf("string",first=0):從first開始查找"string",返回string在str中的第一個(gè)字符的下標(biāo),如果搜不到,輸出-1。
str.search("string") :總是從頭開始查找"string",支持正則表達(dá)式,返回下標(biāo)。
str.match("string"):從頭開始匹配"string",支持正則表達(dá)式,返回存放所有子串的數(shù)組。
str.slice(a,b):提取[a,b)的子串。若為負(fù)數(shù),則表示倒數(shù)幾個(gè)字符。(和python類似)。
str.substr(a,b):從a開始,提取長度為b的子串。
str.toLowerCase():轉(zhuǎn)化成小寫。
str.replace("str1","str2"):把str中的第一個(gè)str1換成str2,如果想把str中的str1都換成str2,要用正則表達(dá)式/str1/g。
str.split(str1):以str1為分隔符,將str劃分,返回?cái)?shù)組(不含str1)。
str.arg(i):把%d換成i。console.log("%1+%2=%3".arg(3).arg(4).arg(7));
正則表達(dá)式:
/"String"/i等價(jià)于RegExp("String","i"),"String"叫模式,"i"叫修飾符。
修飾符:
"i":忽略大小寫。
"g":查找所有符合條件的匹配,而不是在找到第一個(gè)匹配后停止。
"m":跳過換行符匹配。
元字符:
".":匹配除換行符外的任意字符。
"\w":匹配字母,數(shù)字,下劃線或漢字。
"\s":匹配任意空白字符。
"\S":匹配任意非空白字符。
"\d":匹配數(shù)字字符。
"\D":匹配非數(shù)字字符。
"\b":匹配單詞的開始或結(jié)束。
"^":匹配字符串的開始。
"$":匹配字符串的結(jié)束。
量詞:
"*":重復(fù)零次,一次或多次。
"+":重復(fù)一次或多次。
"?":重復(fù)零次或一次。
"{n}":重復(fù)n次。
"{n,}":重復(fù)n次或多次。
"{n,m}":重復(fù)n到m次。
console.log(str.match(/^We.*/mg));
表示匹配所有以We開頭的行。
字符集:[xyz]匹配x,y,z,[0-9]匹配0到9。
轉(zhuǎn)義字符:*,.,\。
正則表達(dá)式可用于String類的search(),match(),replace(),split()方法。
Array類:可變數(shù)組,類型可以不同。
var a=[1,2,3,4,5];
a.push(6,7,8,9):向數(shù)組末尾插入一個(gè)或多個(gè)元素,返回?cái)?shù)組長度。
a.pop():刪除并返回最后一個(gè)元素。
用越界下標(biāo)也可以擴(kuò)充數(shù)組,直接a[6]=7即可,此時(shí)a[5]=undefined。
a.shift():刪除并返回a[0]。
a.unshift(6,7,8,9):從a[0]開始塞進(jìn)去若干元素。
a.sort(cmp):對數(shù)組排序。
數(shù)組的下標(biāo)可以為負(fù)數(shù),負(fù)數(shù)下標(biāo)不會(huì)受到任何方法的影響。如a[-1]=6。
a.join(str):以str為分隔符,將a轉(zhuǎn)化為字符串。
a.concat(b):返回?cái)?shù)組a連接數(shù)組b形成的新數(shù)組。注意:不能寫成a+b。
a.slice(start,end):返回[start,end)的新數(shù)組。
a.splice(index,num):刪除a從index開始的num個(gè)元素,并返回它們組成的數(shù)組。
Math類:
Math.random() 返回0-1之間的隨機(jī)數(shù)。
Date類:
Date()返回現(xiàn)在時(shí)間構(gòu)成的字符串。
Date.now()返回1970.1.1至今的毫秒數(shù),可以用來做計(jì)時(shí)器。
和c++不一樣的是,對象使用完不用delete,直接array=null即可。
函數(shù):
function 函數(shù)名(變量名1,...){}
變量名前面不用寫類型,任何一個(gè)函數(shù)都有返回值,返回值可以為任何類型。
運(yùn)算符:
===:全等于,值和類型都一樣。為了防止null==0。
">>>":帶零擴(kuò)展的右移,移動(dòng)后最左側(cè)補(bǔ)0,負(fù)數(shù)右移后變成正數(shù)。
void():強(qiáng)制轉(zhuǎn)化為undefined。
str instanceof String 判斷str是否是String類型,如果是,返回true,可以用于一般的Object(typeof不行)。
console:
console.time(tag):啟動(dòng)計(jì)時(shí)器,tag是個(gè)字符串。
console.time(tag):停止tag對應(yīng)的計(jì)時(shí)器并輸出時(shí)間。
Global,Math,JSON不需要實(shí)例化就可以使用,被稱作內(nèi)置對象。
QML基本類型:
url:資源地址,可以是本地地址,相對地址和網(wǎng)絡(luò)位置。
encodeURI("url"):把url中無效的空格自動(dòng)替換成/
list:儲(chǔ)存對象的數(shù)組,如item的children屬性,children[i]表示它的第i個(gè)孩子。
enumeration:枚舉類型
Qt.openUrlExternally("url"):打開url,可以是本地文件,也可以用瀏覽器打開網(wǎng)址。
三、Qt Quick 信號處理
信號處理器:on<Signal>:{代碼塊}
附加信號處理器:<別的類型>.on<Signal>:{代碼塊}
如在Rectangle里面用Keys.onEscapePressed:{},表示按下Esc鍵的情況。
Component信號:
Component.onCompleted:組件創(chuàng)建完成時(shí)執(zhí)行的操作。
Component.onDestruction:組件銷毀時(shí)執(zhí)行的操作。
Connections:將多個(gè)對象和一個(gè)信號連接,或者在對象的作用域外使用它的信號。
Connections{
target:發(fā)出信號的對象名
on<Signal>:{
代碼塊;
}
}
(當(dāng)然也可以在Button里面直接寫)
信號分為兩類:輸入操作(鼠標(biāo),鍵盤等)產(chǎn)生的信號,屬性改變產(chǎn)生的信號(on<Property>Changed)。
自定義信號:相當(dāng)于一個(gè)返回值為Signal的函數(shù)
Signal 信號名(屬性名1 參數(shù)1,屬性名2 參數(shù)2...);
當(dāng)需要發(fā)出這個(gè)信號時(shí),調(diào)用此函數(shù)。
在Connection里面用on信號名對這個(gè)信號進(jìn)行處理,這里可以使用Signal函數(shù)的參數(shù)。
Loader:加載組件。
Loader.sourceComponet表示它使用哪個(gè)已有的組件來加載新的組件,這個(gè)已有的組件叫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對象連接到另外的信號或方法上,當(dāng)信號發(fā)射時(shí),連接到信號上的其他信號或方法就會(huì)被調(diào)用。用于一個(gè)信號連接多個(gè)方法。
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);
//當(dāng)clicked被觸發(fā)時(shí),調(diào)用send方法,即send也被觸發(fā)。
}
}
鼠標(biāo):
在一個(gè)item內(nèi)部用MouseArea對象。
enable:true表示開始處理鼠標(biāo)事件。
acceptedButtons設(shè)定接受哪些按鍵,中間用或隔開:Qt.LeftButton|Qt.RightButton|Qt.MidButton
hoverEnabled:true表示開始處理鼠標(biāo)懸停事件。
鼠標(biāo)信號:
clicked:單擊,在內(nèi)部用mouse.button讀取哪個(gè)鍵,mouse.x和mouse.y為鼠標(biāo)坐標(biāo)。
doubleClicked:雙擊。
pressed:按住鼠標(biāo)。
pressAndHold:長按鼠標(biāo)。
released:松開鼠標(biāo)。
entered:鼠標(biāo)進(jìn)入事件區(qū)域。
exited:鼠標(biāo)離開事件區(qū)域。
mouse.accepted=true:鼠標(biāo)事件終止,不再往下傳遞。
鍵盤:
必須先把focus設(shè)成true。
Keys.enabled:true表示開始處理按鍵。
Keys.onPressed:一般按鍵信號,有一個(gè)叫event的參數(shù)。
Keys.onXXXPressed:特殊按鍵信號,如空格,回車等。
Keys.forwardTo:[a,b,c] 表示傳遞給列表內(nèi)的對象,如果某個(gè)對象accept了某個(gè)按鍵,那么列表中排在它后面的對象就不會(huì)收到該按鍵事件。
event.accepted:處理完成標(biāo)記。
event.key:按下的鍵,用于和Qt.Key_x比較。
Keys.priority:設(shè)置Keys附加屬性的優(yōu)先級。Keys.BeforeItem在Item之前處理按鍵(默認(rèn)),Keys.AfterItem在Item之后處理按鍵。比如Item自帶按鍵處理,如果在Item之后處理按鍵,按鍵會(huì)被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會(huì)把信號吃掉,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
}
}
}
計(jì)時(shí)器:Timer
running:true 計(jì)時(shí)器開始工作
onTriggered:每經(jīng)過一個(gè)計(jì)時(shí)周期產(chǎn)生一個(gè)信號。
interval:計(jì)時(shí)周期,默認(rèn)為1000ms。
repeat:true 可以復(fù)位
triggeredOnStart:true 啟動(dòng)后立刻觸發(fā)一次。
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; //設(shè)置臨時(shí)變量,不能用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();
}
}
}
}
四、組件與動(dòng)態(tài)對象
1.Component
既可以定義在單獨(dú)的.qml文件中,也可以在其他item里面定義。
Component只能包含一個(gè)頂層Item,而且除了這個(gè)Item外只能有id。它自己不可見,必須通過Loader實(shí)例化后才可見。定義在單獨(dú)文件中的Component,文件名就是組件名,組件名的首字母必須大寫。
KeyNavigation.left/right/tab:XXX 把focus傳遞給XXX。
一個(gè)完整的實(shí)例:
ColorPicker.qml:
//ColorPicker.qml
//增加了用回車和空格選定的功能
import QtQuick 2.2
Rectangle {
id: colorPicker
width: 50
height: 30
signal colorPicked(color clr);
function configureBorder(){ //當(dāng)focus改變時(shí),用來改變邊框粗細(xì)和顏色的函數(shù)
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){ //染色函數(shù)
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); //這里是函數(shù)名,不是func()
pinkColor.colorPicked.connect(setTextColor);
}
}
}
2.Loader
source:加載qml文檔。
sourceComponent:加載Component對象。
item:指向它加載組件對應(yīng)的頂層對象,如它加載的組件是個(gè)Rectangle,則用item可以訪問那個(gè)Rectangle的屬性和信號。
Loader.item可以作為Connections的target來處理信號。
Loader的尺寸和位置默認(rèn)與Component一樣,可以單獨(dú)在Loader內(nèi)修改。
注意Loader的focus和它對應(yīng)的item的focus不一樣,在Loader里可以直接用item.focus=focus來傳遞,但是在item中要單獨(dú)設(shè)一個(gè)property Item loader,用它的focus來保存它對應(yīng)Loader的focus。
用Loader實(shí)現(xiàn)與上例相同的功能,但是邏輯更復(fù)雜:
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.動(dòng)態(tài)創(chuàng)建和銷毀組件
在Rectangle(rootItem)加一個(gè)標(biāo)記位:property bool colorPickerShow: false;
把sourceComponent改成undefined,這個(gè)組件就隱藏了。
相當(dāng)于一個(gè)狀態(tài)機(jī):當(dāng)click時(shí),根據(jù)現(xiàn)態(tài)是true還是false決定如何轉(zhuǎn)移。
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動(dòng)態(tài)創(chuàng)建對象
Qt.creatComponent("XXX.qml"):創(chuàng)建一個(gè)XXX.qml組件并返回該組件。
Component.creatObject(parent,{"屬性1":XXX,"屬性2":YYY,...}):以parent為父類,以大括號內(nèi)的內(nèi)容為屬性初始值,創(chuàng)建一個(gè)該組件的實(shí)例并返回該實(shí)例。
rootItem.component.status==Component.Ready 判斷組件是否創(chuàng)建成功。
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這個(gè)參數(shù)從createColorPicker傳遞到changeTextColor
}
rootItem.count++;
}
Button{
id: add
text:"add"
anchors.left: parent.left
anchors.leftMargin: 4
anchors.bottom: parent.bottom
anchors.bottomMargin: 4
onClicked:{
//下面這一行書上寫錯(cuò)了
rootItem.createColorPicker(Qt.rgba(Math.random(),
Math.random(),Math.random(),1));
}
}
}
}
5.銷毀動(dòng)態(tài)創(chuàng)建的對象
對于Loader創(chuàng)建的對象,直接把source設(shè)為空串或者把sourceComponent設(shè)置成undefined即可自動(dòng)銷毀。
對于Qt方法創(chuàng)建的對象,調(diào)用其destroy(time=0ms)方法即可銷毀,time為銷毀延遲的時(shí)間。
利用數(shù)組實(shí)現(xiàn)組件的刪除:
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--;
}
}
}
}
五、元素布局
布局定位器:只改變父類的大小,不改變孩子們的尺寸。
布局管理器:根據(jù)界面尺寸變化自動(dòng)調(diào)整孩子們的尺寸。
1.Row和Column
用錨布局設(shè)置行的位置,用spacing屬性設(shè)定Item的間隔,用layoutDirection屬性指定布局方向,默認(rèn)為從左到右,設(shè)定為Qt.RightToLeft時(shí)從右向左。
Column一樣。
2.Grid和Flow
網(wǎng)格,由rows和columns設(shè)置行列數(shù),默認(rèn)為x行4列;rowSpacing和columnSpacing指定行列間距。
flow屬性為放置方法,默認(rèn)為從左到右,放滿一行再放下一行;可以改成Grid.TopToBottom。
Flow:按照自身的寬和高是否超出邊界而自動(dòng)折行。
3.GridLayout
高級的Grid。
要引入import Qtquick.Layouts 1.1
Layout.fillWidth: true 填充一行的所有剩余空間,要提前確定Layout的寬度。
RowLayout、ColumnLayout同理。
六、常用元素
1.TextInput
輸入一行文本。要設(shè)置focus:true才能有效。
maximumLength:設(shè)置編輯框允許輸入字符的最大長度。
echoMode:回顯屬性,默認(rèn)為TextInput.Normal,可以設(shè)置為TextInput.Password:顯示黑圓圈(用Passwordcharacter設(shè)置),TextInput.NoEcho:不回顯。
inputMask:限制輸入字符的格式,如000.000.000.000可以作為ip地址。
IntValidator、RegExpValidator分別為整數(shù)和正則表達(dá)式驗(yàn)證器,用于限制輸入字符的格式。
selectByMouse:true 可以用鼠標(biāo)選擇編輯框內(nèi)的文字。
當(dāng)按下回車鍵或編輯框失去焦點(diǎn)時(shí),會(huì)發(fā)出accepted信號,可以用onAccepted來處理。
2.TextField
高級版TextInput。
textColor:設(shè)置文本顏色,注意不是color。
控件TextFieldStyle的background屬性可以設(shè)定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屬性設(shè)定背景色,但是不能設(shè)置背景圖案,只能用TextEdit底下放個(gè)z序較小的Rectangle對象來實(shí)現(xiàn)。
selectionColor:選中字符邊框的顏色。
selectedTextColor:選中字符的顏色。
TextArea支持鼠標(biāo)和鍵盤的滾動(dòng)。
5.RadioButton
單選。
需要引入import QtQuick.Controls 1.2
ExclusiveGroup:互斥分組,分組內(nèi)的元素只能選一個(gè)。通過按鈕類的exclusiveGroup屬性聲明是哪個(gè)分組。
XXX.current:表示XXX當(dāng)前被選中的元素。
text:顯示文本
checked:顯示RadioButton是否被選中
hovered:指示鼠標(biāo)是否懸停在按鈕上
pressed:按鈕按下時(shí)為true。
activeFocusOnPress:按鈕獲得焦點(diǎn)時(shí)為true。
RadioButtonStyle組件:定制按鈕樣式。
background:定制選項(xiàng)的背景。
indicator:定制選中的指示圖標(biāo)。
label:定制單選按鈕的文本。
control:使用style的RadioButton對象,如control.text為對應(yīng)按鈕旁邊的文字。
spacing:圖標(biāo)和文本之間的間隔。
當(dāng)選中某個(gè)選項(xiàng)時(shí),發(fā)送clicked信號,可以用onClicked處理。
單項(xiàng)選擇示例:
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 //實(shí)現(xiàn)雙擊確定
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 //實(shí)現(xiàn)雙擊確定
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 //實(shí)現(xiàn)雙擊確定
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 //實(shí)現(xiàn)雙擊確定
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設(shè)置樣式。
7.GroupBox
多選,外面加個(gè)邊框。
title:標(biāo)題
checkable:true 標(biāo)題可選
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:"恒水中學(xué)連環(huán)虐殺"
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:[字符串?dāng)?shù)組] 表示下拉選擇的內(nèi)容。
currentText表示當(dāng)前選中的內(nèi)容,currentIndex表示其數(shù)組序號。
9.ProgressBar
進(jìn)度條。
minimumValue:最小值
maximumValue:最大值
value:當(dāng)前值
orientation:Qt.Horizontal水平方向,Qt.Vertical垂直方向。
給進(jìn)度條加百分比:不能只重寫ProgressBarStyle里面的panel,否則進(jìn)度條無法顯示!必須重新載入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
標(biāo)簽頁。
count:標(biāo)簽頁的總數(shù)。
currentIndex:標(biāo)簽頁的序號,從0開始。
tabVisible:默認(rèn)在頂部,Qt.BottomEdge在底部。
addTab(title,component):增添一個(gè)以title為標(biāo)題,以component控件為內(nèi)容的標(biāo)簽頁。
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:設(shè)置最小值,默認(rèn)為0。
maximumValue:設(shè)置最大值,默認(rèn)為1。
value:當(dāng)前值,默認(rèn)為0
onValueChanged:當(dāng)前值改變時(shí),處理信號。
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:畫筆粗細(xì)
strokeStyle:畫筆顏色
fillStyle:填充顏色
beginPath():開始繪制路徑。
moveTo(x,y):將路徑點(diǎn)從紙上拿起來,移動(dòng)到(x,y)。
lineTo(x,y):從當(dāng)前點(diǎn)到(x,y)連一條直線路徑,但是不涂色。
closePath():將路徑終點(diǎn)與起點(diǎn)相連,繪制一條封閉路徑。
stroke():將當(dāng)前路徑用strokeStyle涂色。
fill():若當(dāng)前路徑閉合,則用fillStyle填充顏色。
rect(x1,x2,y1,y2):繪制矩形路徑。
arc(x,y,r,start,end,anticlockwise=1):以(x,y)為圓心,r為半徑,從start到end畫弧路徑,anticlockwise表示是否逆時(shí)針。
createLinearGradient(x1,y1,x2,y2):返回一個(gè)從(x1,y1)到(x2,y2)的線性漸變對象gradient。用gradient.addColorStop(0~1,顏色)來設(shè)置漸變色的邊界點(diǎn)。
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():填充文字和描邊。
設(shè)置字體:ctx.font="42px fantasy" 42像素大小,fantasy字體。
繪制圖片:
drawImage(image,x,y):在(x,y)處繪制image(可以是Image元素或url)。
當(dāng)圖片加載完成時(shí),才能繪制圖片:(放在onPaint下面)
Component.onCompleted: loadImage(source);
onImageLoaded: requestPaint();
可以利用這個(gè)來實(shí)現(xiàn)快速切換圖片。
注意要清空畫布,否則原來的圖片不會(huì)消失。
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):順時(shí)針旋轉(zhuǎn)rad弧度。
scale(x,y):橫向縮放x倍,縱向縮放y倍。
clip():裁剪已有路徑的內(nèi)部。
先繪制路徑,再調(diào)用clip(),最后再調(diào)用drawImage()。
八、動(dòng)畫
1.PropertyAnimation
通過改變對象的property實(shí)現(xiàn)動(dòng)畫。
有3種方法:(1)單獨(dú)聲明一個(gè)PropertyAnimation對象,在信號處理時(shí)調(diào)用animation.start()。(2)on<Signal>:PropertyAnimation+大括號,表示收到信號時(shí)開始運(yùn)行動(dòng)畫。(3)在目標(biāo)對象內(nèi)部用Animation on <property>+大括號:將PropertyAnimation與一個(gè)屬性綁定,然后設(shè)置running:觸發(fā)屬性的條件。
targets:目標(biāo)對象 可以是[obj1,obj2,...]的數(shù)組,也可以是一個(gè)對象。
properties:"width,height" 對象的屬性,多個(gè)屬性用逗號隔開
to:多個(gè)屬性共用的同一個(gè)目標(biāo)值。
duration:持續(xù)時(shí)間(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() 開始運(yùn)行動(dòng)畫
onStarted和onStopped為開始和結(jié)束信號,用一個(gè)var保存當(dāng)前的狀態(tài),可以實(shí)現(xiàn)動(dòng)畫反復(fù)運(yùn)行。
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:動(dòng)畫速度變化模型。默認(rèn)為Easing.Linear。
NumberAnimation,RotationAnimation,ColorAnimation為專用的動(dòng)畫處理器。
2.PathAnimation
讓目標(biāo)對象沿著一個(gè)既定的路徑運(yùn)動(dòng)。
anchorPoint:"x,y" 對象初始位置
orientationEntryDuration:將對象調(diào)整到初始方向所用的時(shí)間
orientationExitDuration:將對象調(diào)整到設(shè)定的終止方向(endRotation)所用的時(shí)間
orientation:控制目標(biāo)對象沿路徑運(yùn)動(dòng)時(shí)的旋轉(zhuǎn)策略。默認(rèn)值為PathAnimation.Fixed保持物體方位不旋轉(zhuǎn)。TopFirst表示目標(biāo)頂部貼合路徑。
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
并行播放動(dòng)畫。
loops:循環(huán)方式。數(shù)字表示循環(huán)幾次,Animation.Infinite表示無限循環(huán)。
animation.pause()表示暫停,此時(shí)animation.paused置1,running置0??梢酝ㄟ^anim.resume()恢復(fù)。
onClicked: {
if(anim.paused) anim.resume();
else if(anim.running) anim.pause();
else anim.start();
}
4.SequentialAnimation
順序播放動(dòng)畫。
5.State
把幾個(gè)屬性綁成一個(gè)狀態(tài)。
states: [State1,State2,...]:狀態(tài)列表。
State{name:"string",when:表達(dá)式,changes:[PropertyChanges,AnchorsChanges等]}
when:當(dāng)表達(dá)式為true時(shí),觸發(fā)狀態(tài)變化。也可以用XXX.state="name"。
explicit:true:只變化一次,false將changes綁定。
6.StateChangeScript和ScriptAction
當(dāng)狀態(tài)改變\調(diào)用start()時(shí),執(zhí)行script:后面的代碼。
name:"name"表示script的名字,可以被ScriptAction對象引用。
這樣雖然邏輯上更直接,但是沒法插入動(dòng)畫。
利用狀態(tài)轉(zhuǎn)移修改屬性:
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
兩個(gè)狀態(tài)之間的過渡動(dòng)畫。
Item的transitions屬性是個(gè)列表,保存Item定義的所有Transition。
scale:縮放系數(shù)。
與state對應(yīng)的動(dòng)畫不用寫target和from to。
對于并行動(dòng)畫,可以直接放在大括號內(nèi),對于順序動(dòng)畫,必須加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綁定動(dòng)畫,當(dāng)property改變時(shí)自動(dòng)播放動(dòng)畫。
一個(gè)Behavior內(nèi)只能有一個(gè)頂層動(dòng)畫。
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
}
}
}
}
}
}
}
一個(gè)完整的對話框?qū)崿F(xiàn):
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: "一個(gè)人的一生應(yīng)該是這樣度過的:當(dāng)他回首往事的時(shí)候,他不會(huì)因?yàn)樘摱饶耆A而悔恨,也不會(huì)因?yàn)槁德禑o為而羞恥;這樣,在臨死的時(shí)候,他就能夠說:“我的整個(gè)生命和全部精力,都已經(jīng)獻(xiàn)給世界上最壯麗的事業(yè)——為人類的解放而斗爭?!?
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();
}
}
}
}
}
}
}