很重要--轉載聲明
- 本站文章無特別說明,皆爲原創,版權全部,轉載時請用連接的方式,給出原文出處。同時寫上原做者:朝十晚八 or Twowords
- 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時經過修改本文達到有利於轉載者的目的。
學習qt已有2年多的時間,從qt4.7開始使用直到如今正在使用的qt5.6,基本都在windows機器上作開發。最近有意向看了下qt的qml部分,覺着仍是挺不錯的,畢竟能夠作嵌入式移動端產品的部分,仍是值的一學。後來在網上看了一些資料,算是初步瞭解了下qml,因此想就本身學習的過程作以記錄,也方便本身理解,若是你有機會看到這篇文章,那麼我認爲你也是來學習qml的,若是你已是一個有很強qml開發經驗的老手,那麼這篇文章和接下來的qml學習系列的文章你都不用看下去了,呵呵。。。git
關於qml的由來,我的覺着Qt的Script、Quick、QML的關係與總結講的不錯,有興趣的同窗能夠去看下。 github
qml的學習過程我主要是以Qt 學習之路 2博客和QmlBook-In-Chinese這本書爲主,同時在作小示例的時候查閱幫助文檔。每一個人的學習方式都不太同樣,若是你有更好的辦法能夠留言。canvas
以下有4張效果圖,分別是4個小示例,關於demo後續章節會有解說,可是都是以代碼中的註解爲主,有興趣的同窗也能夠直接下載示例程序,使用qt提供的qmlscene.exe來直接執行qml文件,或者qmlviewer.exe也能夠預覽qml文件。
windows
圖1 轉動的組件ide
圖2 紅綠燈1工具
圖3 紅綠燈2oop
圖4 GridView使用佈局
一、基本元素post
QML 基本元素能夠分爲可視元素和不可視元素兩類。可視元素:Item
、Rectangle
、Text
、Image
;不可見元素:MouseArea
。關於MouseArea是不可見元素這一點我須要強調一下,由於上邊我提到的兩篇學習文章都沒有說清楚,圖5是qt5.7的幫助文檔截圖,從圖中咱們一眼就能看出結果,MouseArea確實是不可見元素。學習
圖5 MouseArea幫助文檔
關於基本元素我覺着qmlbook這本書相關章節的最後一段說的頗有意思,特此說明,如圖6所示
圖6 qml顯示和交互分開
理解這些基本元素,你能夠認爲他們是一個個被封裝好的類,並且他們有很是之多的屬性,這裏我就不介紹了,由於幫助文檔說的太清楚了。
二、組件
組件其實就是基本元素的複合,放到一個單獨的文件,方便咱們之後重用,關於怎麼建立組件,本節的後續我會給出本身作的示例程序,代碼很簡單只是爲了說明問題
三、定位器
定位器主要有 Row
、Column
、Grid
和Flow
等。
四、元素佈局
除了定位器,咱們還可使用錨(anchor)來佈局元素
五、輸入元素
鍵盤輸入的兩個元素:TextInput
和TextEdit
。TextInput爲一行輸入,TextEdit爲多行輸入
六、quick組件
如表1是Qt Quick Controls 1.1 提供的組件
ApplicationWindow | 對應QMainWindow ,提供頂層應用程序窗口 |
MenuBar | 對應QMenuBar ,提供窗口頂部橫向的菜單欄 |
StatusBar | 對應QStatusBar ,提供狀態欄 |
ToolBar | 對應QToolBar ,提供工具欄,能夠添加ToolButton 和其它組件 |
Action | 對應QAction ,提供可以綁定到導航和視圖的抽象的用戶界面動做 |
導航和視圖 | |
方便用戶在一個佈局中管理和顯示其它組件 | |
ScrollView | 對應QScrollView ,提供滾動視圖 |
SplitView | 對應QSplitter ,提供可拖動的分割視圖佈局 |
StackView | 對應QStackedWidget ,提供基於棧的層疊佈局 |
TabView | 對應QTabWidget ,提供帶有標籤的基於棧的層疊佈局 |
TableView | 對應QTableWidget ,提供帶有滾動條、樣式和表頭的表格 |
控件 | |
控件用於表現或接受用戶輸入 | |
BusyIndicator | 提供忙等示意組件 |
Button | 對應QPushButton ,提供按鈕組件 |
CheckBox | 對應QCheckBox ,提供複選框 |
ComboBox | 對應QComboBox ,提供下拉框 |
GroupBox | 對應QGroupBox ,提供帶有標題、邊框的容器 |
Label | 對應QLabel ,提供標籤組件 |
ProgressBar | 對應QProgressBar ,提供進度條組件 |
RadioButton | 對應QRadioButton ,提供單選按鈕 |
Slider | 對應QSlider ,提供滑動組件 |
SpinBox | 對應QSpinBox ,提供微調組件 |
Switch | 提供相似單選按鈕的開關組件 |
TextArea | 對應QTextEdit ,提供可以顯示多行文本的富文本編輯框 |
TextField | 對應QTextLine ,提供顯示單行文本的純文本編輯框 |
ToolButton | 對應QToolButton ,提供在工具欄上顯示的工具按鈕 |
ExclusiveGroup | 提供互斥 |
菜單 | |
用於構建菜單的組件 | |
Menu | 對應QMenu ,提供菜單、子菜單、彈出菜單等 |
MenuSeparator | 提供菜單分隔符 |
MenuItem | 提供添加到菜單欄或菜單的菜單項 |
StatusBar | 對應QStatusBar ,提供狀態欄 |
ToolBar | 對應QToolBar ,提供工具欄,能夠添加ToolButton 和其它組件 |
表1 Qt Quick Controls 1.1組件
七、模型和視圖
模型和視圖其實屬於qml的高級使用部分了,可是爲了能早些理解qml的東西,我提早拿出一些簡單的東西,預先學習下。
八、canvas畫布
在早些qt4時代,qml只提供了幾種基礎元素,第一小節也說明了,有不少人指望的圓角矩形,橢圓和圓,可是最終官方沒有給出具體的元素,若是是要作這些組件,那麼就須要設計師給切圖。到了qt5,官方提供了canvas畫布,這個畫布能夠實現複雜的繪圖操做,而且畫布元素是基於HTML5的畫布元素來完成的。支持畫筆,填充,漸變,文本和繪製路徑建立命令。
接下里就是第二節所展現的效果圖對於代碼講解了,那我也就按照上圖展現的順序一個個講解代碼
一、基礎組件講解
在開始示例講解以前,我先說下我本身封裝的一個小組件,代碼量不多,只爲說明問題,具體請看diamante
1 import QtQuick 2.5 2 3 // 圓角矩形框矩形框,支持點擊 4 Rectangle { 5 property alias text: name.text;//導出文本變量 6 property alias textColor: name.color;//導出文本顏色 7 8 id: root; 9 width: 120; 10 height: 120; 11 radius:60; 12 antialiasing: true; 13 signal clicked();//自定義信號 外部能夠經過onClicked接收 14 15 MouseArea 16 { 17 width: root.width; 18 height: root.height; 19 20 onClicked: 21 { 22 //鼠標點擊時發送消息 並輸入日誌 23 root.clicked(); 24 console.log("rectangle clicked"); 25 } 26 } 27 28 Text 29 { 30 id: name; 31 text: ""; 32 color: "black"; 33 anchors.centerIn: parent; 34 } 35 }
二、旋轉的風車,代碼裏有多種方式實現矩形旋轉,具體使用那一種就由我的喜愛了
import QtQuick 2.0 import QtQuick.Window 2.0 import QtGraphicalEffects 1.0 import "../contrl" //導入自定義組件模塊 Window { id:root; visible: true; width: 600; height: 400; //背景色窗口 Rectangle { id: bg; color:"lightsteelblue"; width: root.width; height:root.height; } //鼠標點擊背景色時中止旋轉圖形 MouseArea { width: bg.width; height: bg.height; onClicked: { ro.pause(); } } //自定義控件 經過import導入 Rect { id: roundItem; anchors.centerIn: parent; //漸變填充矩形 ConicalGradient { anchors.fill: parent gradient: Gradient { GradientStop { position: 0.0; color: "lightsteelblue" } GradientStop { position: 1.0; color: "blue" } } } //旋轉動畫1 程序剛啓動會執行 緣由未知 // NumberAnimation on rotation { // loops:Animation.Infinite; // from:0; // to:360; // duration: 1000; // } //旋轉動畫2 配合wheel.rotation = 360;使用 動畫 不能循環執行 // Behavior on rotation { // NumberAnimation { // loops:Animation.Infinite;//無效 // duration: 1000; // } // } //旋轉動畫3 相比於動畫1 在屬性中主動指明瞭target和property // NumberAnimation { // id:ro; // loops:Animation.Infinite; // property: "rotation"; // target:roundItem; // from:0; // to:360; // duration: 1000; // } //旋轉動畫4 和動畫1是同樣的 由於RotationAnimation和NumberAnimation都是繼承自PropertyAcimation //所以RotationAnimation動畫能夠實現和動畫2同樣的效果,使用RotationAnimation // RotationAnimation on rotation { // loops: Animation.Infinite; // from: 0; // to: 360; // duration: 1000; // } //旋轉動畫5 RotationAnimation { id:ro; target:roundItem; loops: Animation.Infinite; from: 0; to: 360; duration: 1000; } onClicked: { if (ro.paused) { ro.resume(); } else { ro.start(); } } } }
三、紅綠燈,下述代碼紅色的的切換時經過鼠標單擊進行
1 import QtQuick 2.0 2 import QtQuick.Window 2.0 3 import QtGraphicalEffects 1.0 4 5 import "../contrl" 6 7 Window 8 { 9 function dosomething()//測試script腳本運行效果 10 { 11 console.log("do something"); 12 } 13 14 id:root; 15 visible: true; 16 width: 370; 17 height: 130; 18 19 Rectangle 20 { 22 id:rootRect; 23 width: root.width; 24 height:root.height; 25 anchors.centerIn:parent; 26 27 Row 28 { 29 id:ligheGroup; 30 spacing: 2; 31 states: 32 [ 33 State { 34 name: "red" 35 // StateChangeScript {name: "myScript"; script: dosomething(); } //能夠正常調用 36 PropertyChanges { 37 target: redLight; color:"red"; 38 } 39 PropertyChanges { 40 target: greenLight; color:"black"; 41 } 42 PropertyChanges { 43 target: yellowLight; color:"black"; 44 } 45 }, 46 State { 47 name: "green" 48 PropertyChanges { 49 target: redLight; color:"black"; 50 } 51 PropertyChanges { 52 target: greenLight; color:"green"; 53 } 54 PropertyChanges { 55 target: yellowLight; color:"black"; 56 } 57 }, 58 State { 59 name: "yellow" 60 PropertyChanges { 61 target: redLight; color:"black"; 62 } 63 PropertyChanges { 64 target: greenLight; color:"black"; 65 } 66 PropertyChanges { 67 target: yellowLight; color:"yellow"; 68 } 69 } 70 ] 71 72 anchors.centerIn:parent; 73 Rect//紅燈 74 { 75 id:redLight; 76 color:"black"; 77 radius: width/2; 78 } 79 Rect//綠燈 80 { 81 id:greenLight; 82 color:"black"; 83 radius: width/2; 84 } 85 Rect//黃燈 86 { 87 id:yellowLight; 88 color:"black"; 89 radius: width/2; 90 } 91 92 transitions: 93 [ 94 Transition //提供從red狀態到yellow狀態的漸變過程 95 { 96 from: "red" 97 to: "yellow" 98 // ScriptAction { script: dosomething(); } //能夠正常調用 99 ColorAnimation{ target: redLight; properties: "color";duration: 1000;} 100 ColorAnimation{ target: yellowLight; properties: "color";duration: 1000;} 101 } 102 ] 103 } 104 property bool m_bIsRed : false; 105 MouseArea 106 { 107 anchors.fill: parent; 108 onClicked://鼠標點擊時,狀態切換 109 { 110 if (ligheGroup.state == "red" 111 || ligheGroup.state == "green") 112 { 113 ligheGroup.state = "yellow"; 114 } 115 else 116 { 117 if (parent.m_bIsRed == false) 118 { 119 ligheGroup.state = "red"; 120 parent.m_bIsRed = true; 121 } 122 else 123 { 124 ligheGroup.state = "green"; 125 parent.m_bIsRed = false; 126 } 127 } 128 } 129 } 130 } 131 }
四、紅綠燈,不一樣於上述紅綠燈,次紅綠燈只須要鼠標單擊觸發運行,狀態是由定時器來控制,紅燈運行60秒,綠燈20秒,黃燈3秒,爲了程序的迅速反應,在紅燈和綠燈的時候定時器觸發頻率全部提升,具體請看代碼,此處我只貼出定時器部分,若是須要整個運行程序,可自行下載demo。
1 property bool m_bIsRed : false;//是不是紅燈亮 2 property int m_iTicker : 0; 3 4 Timer 5 { 6 id:redState; 7 interval: 50;//每隔50毫秒觸發一次,真實狀況下本應該是1000毫秒一次 8 repeat: true; 9 triggeredOnStart: true; 10 property int count : 60;//紅燈秒數 11 12 onTriggered: { 13 if (lightGroup.state != "red") 14 { 15 lightGroup.state = "red"; 16 root.m_bIsRed = true; 17 } 18 19 ++m_iTicker; 20 redLight.text = count - m_iTicker; 21 if (count <= m_iTicker)//到達指定時間 重置計數器,並切換到黃燈定時器,關閉自身定時器 22 { 23 m_iTicker = 0; 24 yellowState.start(); 25 redState.stop(); 26 } 27 } 28 } 29 Timer 30 { 31 id:yellowState; 32 interval: 1000; 33 repeat: true; 34 triggeredOnStart: true; 35 property int count : 3;//黃燈秒數 36 37 onTriggered: { 38 if (lightGroup.state != "yellow") 39 { 40 lightGroup.state = "yellow"; 41 } 42 ++m_iTicker; 43 yellowLight.text = count - m_iTicker; 44 if (count <= m_iTicker)//到達指定時間 重置計數器,並切換到綠燈/紅燈定時器,關閉自身定時器 45 { 46 m_iTicker = 0; 47 if (m_bIsRed) 48 { 49 greenState.start(); 50 } 51 else 52 { 53 redState.start(); 54 } 55 stop(); 56 } 57 } 58 } 59 Timer 60 { 61 id: greenState; 62 interval: 150;//每隔150毫秒觸發一次,真實狀況下本應該是1000毫秒一次 63 repeat: true; 64 triggeredOnStart: true; 65 property int count : 20;//綠燈秒數 66 67 onTriggered: { 68 if (lightGroup.state != "green") 69 { 70 lightGroup.state = "green"; 71 root.m_bIsRed = false; 72 } 73 74 ++m_iTicker; 75 greenLight.text = count - m_iTicker; 76 if (count <= m_iTicker)//到達指定時間 重置計數器,並切換到黃燈定時器,關閉自身定時器 77 { 78 m_iTicker = 0; 79 yellowState.start(); 80 greenState.stop(); 81 } 82 } 83 }
五、日曆窗口,代碼量不大,有興趣的能夠看看,主要就是界面展現,若是想要作到動態的日曆,須要對模型動態的增刪,這個功能後續咱們在完善。
1 import QtQuick 2.6 2 import QtQuick.Window 2.0 3 import QtGraphicalEffects 1.0 4 5 import "../contrl" 6 7 Window 8 { 9 visible: true; 10 width: 300; 11 height: 300; 12 13 Rectangle 14 { 15 id:root; 16 anchors.fill: parent; 17 width: root.width; 18 height: root.height; 19 color: "yellow"; 20 21 //日期頭 22 Row 23 { 24 id: weekname; 25 spacing: 2; 26 padding: 5; 27 28 Repeater 29 { 30 model: ["周天", "週一", "週二", "週三", "週四", "週五", "週六"] 31 Rectangle 32 { 33 width: (root.width - 6 * weekname.spacing - 10) / 7; 34 height: 30 35 radius: 3 36 color: "lightBlue" 37 Text 38 { 39 anchors.centerIn: parent 40 text: modelData 41 } 42 } 43 } 44 } 45 46 //天 47 GridView 48 { 49 id: weekday; 50 boundsBehavior: Flickable.StopAtBounds; 51 anchors//佈局 52 { 53 top: weekname.bottom; 54 left:root.left; 55 leftMargin:5; 56 right: root.right; 57 rightMargin:5; 58 bottom: root.bottom; 59 } 60 model: 42;//天數 61 62 cellWidth: (root.width - 10) / 7; 63 cellHeight: (root.width - 10) / 7; 64 // Repeater 65 // { 66 // Rectangle 67 // { 68 // radius: 8; 69 // color: "lightBlue"; 70 // Text 71 // { 72 // anchors.centerIn: parent; 73 // text: modelData; 74 // } 75 // } 76 // } 77 delegate: numberDelegate; 78 focus: true;//能夠獲取焦點 79 } 80 81 Component//繪製代理 82 { 83 id: numberDelegate; 84 Rectangle 85 { 86 width: weekday.cellWidth; 87 height: weekday.cellHeight; 88 color: GridView.isCurrentItem ? "green" : "lightGreen"//根據是不是當前項設置顏色 89 border.color: Qt.lighter("green"); 90 Text 91 { 92 anchors.centerIn: parent; 93 font.pixelSize: 10; 94 text: index + 1;//文本取索引值 95 } 96 } 97 } 98 } 99 }
補充:示例代碼中:GridView中的repeater元素是不須要的,repeater是配合定位器使用的模型,由於每個repeater都包含一個默認的繪製代理。
注:這是qml學習系列的第一篇文章,後邊我還會以這種示例的形式繼續更新更多學習的進度,但願你們多多支持,有問題的小夥伴能夠私信我。謝謝。。。