Qt Quick/QML學(xué)習(xí)筆記

(基于qt 5.3.1)

一、Qt Quick入門

1.啟動(dòng)Qt Quick App的兩種方式
(1)窗口標(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
    }
}

(2)窗口標(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對象
(1)visibility:控制窗口最小化、最大化、全屏等。
直接在Window里面加入:

    visibility: Window.Minimized 
    visibility: Window.Maximized
    visibility: Window.FullScreen

(2)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();
                        }
                    }
                }
            }
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容