4.3 Text 元素
在需要顯示文本的場合,我們可以使用 Text 元素。它最顯著的屬性是 string 類型的 text 屬性。Text 元素會根據(jù)給定的文本和其使用的字體計算其初始時的寬度和高度。字體的屬性值可以使用字體屬性組來進行設置(例如:font.family,font.pixelSize 等等)。如果要改變文本的顏色,只需使用 color 屬性即可。
例如下面的代碼:
Text {
text: "The quick brown fox"
color: "#303030"
font.family: "Ubuntu"
font.pixelSize: 28
}
的顯示效果為:

Text 元素能夠通過水平對齊(horizontalAlignment)和垂直對齊(verticalAlignment)屬性對齊到相應的一側或者居中。為了進一步增強文本的渲染效果,我們可以使用 style 和 styleColor 屬性,這允許我們將文本以輪廓(outline)、凸起(raised )和下沉(sunken )模式呈現(xiàn)。對于較長的文本,我們通常會需要定義一個省略(以 ... 代替無法顯示的內容)顯示的位置。這可以使用 elide 屬性來實現(xiàn)。elide 屬性允許我們將想要省略顯示的位置設置為文本的左(left)、右(right)或中間(middle)。有時我們希望看到整個文本的內容,而不是以“...”的形式省略部分內容的顯示,該如何處理呢?此時我們可以使用 wrapMode 屬性,它以 Text 元素的寬度為依據(jù)對文本的內容進行折行顯示:
Text {
width: 40; height: 120
text: 'A very long text'
// '...' shall appear in the middle
elide: Text.ElideMiddle
// red sunken text styling
style: Text.Sunken
styleColor: '#FF4444'
// align text to the top
verticalAlignment: Text.AlignTop
// only sensible when no elide mode
// wrapMode: Text.WordWrap
}
Text 元素僅用來展示給定的文本內容。它不會渲染任何的背景元素。除了要呈現(xiàn)的文本內容外,文本元素是透明的。因此,為文本元素提供了一個合理的背景,將是我們整體設計的一部分。
** 注意: **
請注意 Text 元素的初始寬度(width)或高度(height)取決于文本字符串和字體集。沒有設置寬度、高度或 text 屬性的內容的 Text 元素將不可見,因為 Text 元素初始寬度和高度為 0,text 屬性的內容默認為空。
** 注意: **
通常當我們想要布局 Text 元素時,我們需要區(qū)別 Text 元素內的文本內容的布局和 Text 元素自身的布局。在前者中,我們需要使用水平對齊(horizontalAlignment)和垂直對齊(verticalAlignment)屬性,在后面的情形中我們需要使用的是在其他元素中使用的相類似定位和布局方式。例如:
Rectangle {
width: 400
height: 600
Text {
// 后面的情形
width: 100
height: 60
anchors.centerIn: parent
// 前面的情形
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
}
也就是前者指對內容的定位,后者指對元素的定位。
4.4 Image 元素
Image 元素能夠用于顯示多種格式的圖像(例如 PNG、JPG、GIF、BMP、WEBP 等)。對于支持的圖像格式的完整列表,請參考 Qt 文檔。除了提供了明顯的 URL 類型的屬性 source 用于指定圖片源之外,Image 元素還包含了一個用于控制縮放行為的 fillMode 屬性。
Image {
x: 12; y: 12
// width: 72
// height: 72
source: "assets/triangle_red.png"
}
Image {
x: 12+64+12; y: 12
// width: 72
height: 72/2
source: "assets/triangle_red.png"
fillMode: Image.PreserveAspectCrop
clip: true
}

** 注意: **
URL 可以是帶有前斜杠的本地路徑 (例如: ./imag/home.png) 或網絡鏈接 (例如:http://example.org/home.png )。
** 注意: **
Image 元素使用 fillMode 屬性的 PreserveAspectCrop 值也可以實現(xiàn)對圖像的剪切效果,以避免在圖像邊界之外呈現(xiàn)圖像數(shù)據(jù)內容。默認情況下剪切屬性是不可用的(即 clip: false)。我們可以將剪切屬性使能(即 clip: true)來將這圖片約束到元素的邊界范圍內。當然,這個剪切屬性是可以在任何可視元素上使用的。
** 提示: **
使用 C++ 可以創(chuàng)建自己的圖像提供程序,具體可以參見 QQuickImageProvider 的文檔。這允許我們可以實現(xiàn)在動態(tài)和線程圖像加載的情況下創(chuàng)建圖像。
4.5 MouseArea 元素
為了進行元素間的交互,我們通常會用到 MouseArea 元素。它是一個矩形的透明元素,我們可以在其中捕獲鼠標事件。當用戶與可視元素交互時,MouseArea 通常與可見元素一起使用以執(zhí)行命令。
Rectangle {
id: rect1
x: 12; y: 12
width: 76; height: 96
color: "lightsteelblue"
MouseArea {
id: area
width: parent.width
height: parent.height
onClicked: rect2.visible = !rect2.visible
}
}
Rectangle {
id: rect2
x: 112; y: 12
width: 76; height: 96
border.color: "lightsteelblue"
border.width: 4
radius: 8
}


** 注意: **
這是 Qt Quick 的一個重要方面,輸入處理與可視化顯示相互分離。通過這種方式,我們可以輕松地實現(xiàn)在向用戶顯示一個可視的接口元素的同時,提供比可視區(qū)域更大的交互區(qū)域。
4.6 Component (組件)元素
Component (組件)是可重用的元素,QML 提供了不同的方法來創(chuàng)建組件。目前,我們只看最簡單的形式 —— 基于文件的組件。通過將 QML 元素放置在文件中并賦予該文件一個元素名,創(chuàng)建了一個基于文件的組件(例如: MyButton.qml )。我們可以像 QtQuick 模塊中的其他元素一樣使用組件,在我們的例子中,我們可以在代碼中使用這個組件:
MyButton {
...
}
例如,讓我們創(chuàng)建一個包含文本組件和鼠標區(qū)域的矩形。這就像一個簡單的按鈕,為了演示不需要很復雜。
Rectangle { // 內聯(lián)的按鈕
id: button
x: 12; y: 12
width: 116; height: 26
color: "lightsteelblue"
border.color: "slategrey"
Text {
anchors.centerIn: parent
text: "Start"
}
MouseArea {
anchors.fill: parent
onClicked: {
status.text = "Button clicked!"
}
}
}
Text { // 當按鈕點擊的時候文本內容改變
id: status
x: 12; y: 76
width: 116; height: 26
text: "waiting ..."
horizontalAlignment: Text.AlignHCenter
}
上面的示例的運行效果看起來與下面的兩張圖片類似。先是初始狀態(tài)的 UI 效果,在按鈕被單擊后的效果是下面的圖片。


現(xiàn)在我們的任務是在可重用組件(Component)中提取按鈕 UI。為此,我們考慮了一個可能的按鈕 API。我們可以通過想象別人如何使用你的按鈕來實現(xiàn)這一點。以下是我們的簡單示例:
// minimal API for a button
MyButton {
text: "Click Me"
onClicked: { // do something }
}
我們使用 text 屬性設置文本,并實現(xiàn)我們自己的單擊處理程序。另外,我們可能還希望按鈕具有一個合理的初始大小,例如 width: 240。
為實現(xiàn)這一目標,我們首先創(chuàng)建一個名為 MyButton.qml 的文件。然后復制我們之前例子中的簡單按鈕的實現(xiàn)代碼到這個文件中。另外,我們需要導出用戶可能想要在根級別上更改的屬性。這將使得我們的文件內容看起來類似下面這樣:
// MyButton.qml
import QtQuick 2.0
Rectangle {
id: root
// export button properties
property alias text: label.text
signal clicked
width: 116; height: 26
color: "lightsteelblue"
border.color: "slategrey"
Text {
id: label
anchors.centerIn: parent
text: "Start"
}
MouseArea {
anchors.fill: parent
onClicked: {
root.clicked()
}
}
}
我們已經導出了 text 屬性并在根級上創(chuàng)建了 clicked 信號。通常,我們命名根元素 root 來使引用更容易。我們使用 QML 的 alias (別名)特性,這是一種將嵌套的 QML 元素內的屬性導出到根級別并使其可用于外部的方法。重要的是要知道,只有根級別的屬性可以通過其他組件從這個文件外部訪問。
要使用我們的 MyButton 元素,我們可以簡單地在我們的文件中聲明它。這樣我們在前面介紹的例子會變得簡單一些:
Button { // our Button component
id: button
x: 12; y: 12
text: "Start"
onClicked: {
status.text = "Button clicked!"
}
}
Text { // text changes when button was clicked
id: status
x: 12; y: 76
width: 116; height: 26
text: "waiting ..."
horizontalAlignment: Text.AlignHCenter
}
現(xiàn)在你可以在 UI 中使用任意多的按鈕 MyButton { ... }。一個真正的按鈕可能更復雜,例如:當點擊時,提供反饋或者顯示出更好的裝飾效果。
** 注意: **
就個人而言,我們甚至可以更進一步,使用一個 Item 作為根元素。這可以防止用戶更改我們設計的按鈕的顏色,并為導出的 API 提供更多的控制。我們的目標應該是導出一個最小的 API。實際上,這意味著我們需要用一個 Item 來替換根矩形( Rectangle ),并在根項目( Item )中使矩形( Rectangle )成為一個嵌套的元素。
Item {
id: root
width: 116; height: 26
property alias text: label.text
signal clicked
Rectangle {
anchors.fill parent
color: "lightsteelblue"
border.color: "slategrey"
}
...
}
有了(本節(jié)介紹的)這種技術,就可以很容易地創(chuàng)建一系列可重用的組件。
本文參考鏈接:Quick Starter