QML對(duì)象屬性
每個(gè)QML對(duì)象類型都有一組定義的屬性。使用為該對(duì)象類型定義的屬性集創(chuàng)建對(duì)象類型的每個(gè)實(shí)例??梢灾付◣追N不同的屬性,如下所述。
對(duì)象聲明中的屬性
QML文檔中的對(duì)象聲明(object declaration)定義了一種新類型。它還聲明了一個(gè)對(duì)象層次結(jié)構(gòu),如果創(chuàng)建該新定義類型的實(shí)例,則將實(shí)例化該對(duì)象層次結(jié)構(gòu)。
QML對(duì)象類型屬性類型的集合如下:
- ID屬性
- 屬性屬性
- 信號(hào)屬性
- 信號(hào)處理程序?qū)傩?/li>
- 方法屬性
- 附加屬性和附加信號(hào)處理程序?qū)傩?/li>
- 枚舉屬性
這些屬性將在下面詳細(xì)討論。
ID屬性
每個(gè)QML對(duì)象類型都有一個(gè)唯一的id屬性。此屬性由語言本身提供,并且不能由任何QML對(duì)象類型重新定義或覆蓋。
可以將值分配給對(duì)象實(shí)例的id屬性,以允許該對(duì)象被其他對(duì)象標(biāo)識(shí)和引用。它id必須以小寫字母或下劃線開頭,并且不能包含字母,數(shù)字和下劃線以外的字符。
import QtQuick 2.0
Column {
width: 200; height: 200
TextInput { id: myTextInput; text: "Hello World" }
Text { text: myTextInput.text }
}
可以在聲明對(duì)象id的組件范圍內(nèi)的任何位置引用該對(duì)象。因此,id值在其組成范圍內(nèi)必須始終是唯一的。有關(guān)更多信息,請(qǐng)參見作用域和命名分辨率。
創(chuàng)建對(duì)象實(shí)例后,無法更改其id屬性的值。盡管它看起來像是普通屬性,但該id屬性不是普通property屬性,并且特殊語義適用于此屬性;例如,myTextInput.id在上面的示例中無法訪問。
屬性Property
屬性是可以分配靜態(tài)值或綁定到動(dòng)態(tài)表達(dá)式的對(duì)象的屬性。一個(gè)屬性的值可以被其他對(duì)象讀取。通常,它也可以由另一個(gè)對(duì)象修改,除非特定的QML類型明確禁止特定屬性使用。
定義Property屬性
通過注冊(cè)類的Q_PROPERTY,然后再向QML類型系統(tǒng)注冊(cè),可以在C ++中為類型定義屬性?;蛘?,可以使用以下語法在QML文檔的對(duì)象聲明中定義對(duì)象類型的自定義屬性:
[default] property <propertyType> <propertyName>
這樣,對(duì)象聲明可以將特定的值暴露給外部對(duì)象,或者更容易維護(hù)一些內(nèi)部狀態(tài)。
屬性名稱必須以小寫字母開頭,并且只能包含字母,數(shù)字和下劃線。JavaScript保留字不是有效的屬性名稱。該default關(guān)鍵字是可選的,并修改所聲明的屬性的語義。有關(guān)屬性修飾符的更多信息,請(qǐng)參見后面的默認(rèn)屬性部分default。
聲明自定義屬性會(huì)隱式創(chuàng)建該屬性的值更改信號(hào),以及一個(gè)名為on <PropertyName> Changed的關(guān)聯(lián)信號(hào)處理程序,其中<PropertyName>是屬性的名稱,首字母大寫。
例如,以下對(duì)象聲明定義了一個(gè)從Rectangle基本類型派生的新類型。它具有兩個(gè)新屬性,并為這些新屬性之一實(shí)現(xiàn)了信號(hào)處理程序:
Rectangle {
property color previousColor
property color nextColor
onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}
自定義屬性定義中的有效類型
除枚舉類型外,任何QML基本類型都可用作自定義屬性類型。例如,這些都是有效的屬性聲明:
Item {
property int someNumber
property string someString
property url someUrl
}
(枚舉值只是整數(shù)值,可以用int類型來引用。)
QtQuick模塊提供了一些基本類型,因此除非導(dǎo)入模塊,否則它們不能用作屬性類型。有關(guān)更多詳細(xì)信息,請(qǐng)參見QML基本類型文檔。
請(qǐng)注意,var基本類型是通用占位符類型,可以保存任何類型的值,包括列表和對(duì)象:
property var someNumber: 1.5
property var someString: "abc"
property var someBool: true
property var someList: [1, 2, "three", "four"]
property var someObject: Rectangle { width: 100; height: 100; color: "red" }
此外,任何QML對(duì)象類型都可以用作屬性類型。例如:
property Item someItem
property Rectangle someRectangle
這也適用于自定義QML類型。如果在名為ColorfulButton.qml(在隨后由客戶端導(dǎo)入的目錄中)文件中定義了QML類型,則type屬性ColorfulButton也將有效。
將值分配給屬性
可以通過兩種不同的方式指定對(duì)象實(shí)例的屬性的值:
- 初始化時(shí)的值分配
- 必要的價(jià)值分配
無論哪種情況,該值都可以是靜態(tài)值或綁定表達(dá)式值。
初始化時(shí)的值分配
在初始化時(shí)為屬性分配值的語法是:
<propertyName> : <value>
如果需要,可以將初始化值分配與對(duì)象聲明中的屬性定義組合。在這種情況下,屬性定義的語法變?yōu)椋?/p>
[default] property <propertyType> <propertyName> : <value>
屬性值初始化的示例如下:
import QtQuick 2.0
Rectangle {
color: "red"
property color nextColor: "blue" // combined property declaration and initialization
}
命令性價(jià)值分配
命令性值分配是將屬性值(靜態(tài)值或綁定表達(dá)式)從命令性JavaScript代碼分配給屬性的地方。強(qiáng)制性值賦值的語法只是JavaScript賦值運(yùn)算符,如下所示:
[<objectId>.]<propertyName> = value
強(qiáng)制性值分配的示例如下:
import QtQuick 2.0
Rectangle {
id: rect
Component.onCompleted: {
rect.color = "red"
}
}
靜態(tài)值和綁定表達(dá)式值
如前所述,可以為屬性分配兩種值:靜態(tài)值和綁定表達(dá)式值。后者也稱為屬性綁定。
| 類 | 語義學(xué) |
|---|---|
| 靜態(tài)值 | 一個(gè)不依賴于其他屬性的常數(shù)值。 |
| 綁定表達(dá) | 一個(gè)JavaScript表達(dá)式,用于描述屬性與其他屬性的關(guān)系。此表達(dá)式中的變量稱為屬性的依賴項(xiàng)。 |
QML引擎強(qiáng)制執(zhí)行屬性及其依賴項(xiàng)之間的關(guān)系。當(dāng)任何依賴項(xiàng)的值發(fā)生變化時(shí),QML引擎都會(huì)自動(dòng)重新計(jì)算綁定表達(dá)式并將新結(jié)果分配給該屬性。
|
這是一個(gè)示例,顯示了兩種分配給屬性的值:
import QtQuick 2.0
Rectangle {
// both of these are static value assignments on initialization
width: 400
height: 200
Rectangle {
// both of these are binding expression value assignments on initialization
width: parent.width / 2
height: parent.height
}
}
注意:要強(qiáng)制分配綁定表達(dá)式,綁定表達(dá)式必須包含在傳遞給Qt.binding()的函數(shù)中,然后必須將Qt.binding()返回的值分配給該屬性。相反,在初始化時(shí)分配綁定表達(dá)式時(shí),不得使用Qt.binding()。有關(guān)更多信息,請(qǐng)參見屬性綁定。
類型安全
屬性是類型安全的。只能為屬性分配與屬性類型匹配的值。
例如,如果一個(gè)屬性是一個(gè)實(shí)數(shù),并且如果您嘗試為其分配一個(gè)字符串,則會(huì)出現(xiàn)錯(cuò)誤:
property int volume: "four" // generates an error; the property's object will not be loaded
同樣,如果在運(yùn)行時(shí)為屬性分配了錯(cuò)誤類型的值,則不會(huì)分配新值,并且會(huì)生成錯(cuò)誤。
某些屬性類型沒有自然值表示形式,對(duì)于這些屬性類型,QML引擎自動(dòng)執(zhí)行字符串到類型值的轉(zhuǎn)換。因此,例如,即使color類型的屬性存儲(chǔ)顏色而不是字符串,您也可以將字符串分配給"red"color屬性,而不會(huì)報(bào)告錯(cuò)誤。
有關(guān)默認(rèn)支持的屬性類型的列表,請(qǐng)參見QML基本類型。另外,任何可用的QML對(duì)象類型也可以用作屬性類型。
特殊財(cái)產(chǎn)類型
對(duì)象列表屬性屬性
甲列表類型屬性可被分配QML對(duì)象類型值的列表。定義對(duì)象列表值的語法是用方括號(hào)括起來的逗號(hào)分隔列表:
[ <item 1>, <item 2>, ... ]
例如,Item類型具有一個(gè)states屬性,該屬性用于保存State類型對(duì)象的列表。下面的代碼將該屬性的值初始化為三個(gè)State對(duì)象的列表:
import QtQuick 2.0
Item {
states: [
State { name: "loading" },
State { name: "running" },
State { name: "stopped" }
]
}
如果列表包含單個(gè)項(xiàng)目,則可以省略方括號(hào):
import QtQuick 2.0
Item {
states: State { name: "running" }
}
列表類型屬性可以與下面的語法的對(duì)象聲明中指定:
[default] property list<<objectType>> propertyName
并且,與其他屬性聲明一樣,可以使用以下語法將屬性初始化與屬性聲明結(jié)合使用:
[default] property list<<objectType>> propertyName: <value>
列表屬性聲明的示例如下:
import QtQuick 2.0
Rectangle {
// declaration without initialization
property list<Rectangle> siblingRects
// declaration with initialization
property list<Rectangle> childRects: [
Rectangle { color: "red" },
Rectangle { color: "blue"}
]
}
如果您希望聲明一個(gè)屬性來存儲(chǔ)值列表,這些列表不一定是QML對(duì)象類型的值,則應(yīng)該聲明一個(gè)var屬性。
分組屬性
在某些情況下,屬性包含一組邏輯的子屬性屬性??梢允褂命c(diǎn)符號(hào)或組符號(hào)將這些子屬性屬性分配給它們。
例如,“ 文本”類型具有字體組屬性。下面,第一個(gè)Text對(duì)象font使用點(diǎn)表示法初始化其值,而第二個(gè)對(duì)象使用組表示法:
Text {
//dot notation
font.pixelSize: 12
font.b: true
}
Text {
//group notation
font { pixelSize: 12; b: true }
}
分組屬性類型是具有子屬性的基本類型。這些基本類型中的一些是由QML語言提供的,而其他一些僅在導(dǎo)入Qt Quick模塊時(shí)才可以使用。有關(guān)更多信息,請(qǐng)參見有關(guān)QML基本類型的文檔。
屬性別名(Property Aliases)
屬性別名是保存對(duì)另一個(gè)屬性的引用的屬性。與為屬性分配新的唯一存儲(chǔ)空間的普通屬性定義不同,屬性別名將新聲明的屬性(稱為別名屬性)連接為對(duì)現(xiàn)有屬性(別名屬性)的直接引用。
屬性別名聲明看起來像普通的屬性定義,只是它需要alias關(guān)鍵字而不是屬性類型,并且屬性聲明的右側(cè)必須是有效的別名引用:
[default] property alias <name>: <alias reference>
與普通屬性不同,別名具有以下限制:
- 它只能引用在聲明別名的類型范圍內(nèi)的對(duì)象或?qū)ο蟮膶傩浴?/li>
- 它不能包含任意JavaScript表達(dá)式
- 它不能引用在其類型范圍之外聲明的對(duì)象。
- 該別名引用是不可選的,不像普通的財(cái)產(chǎn)可選默認(rèn)值; 首次聲明別名時(shí),必須提供別名引用。
- 它不能引用附加屬性。
- 它不能引用深度為3或更大的層次結(jié)構(gòu)內(nèi)的屬性。以下代碼不起作用:
property alias color: myItem.myRect.border.color
Item {
id: myItem
property Rectangle myRect
}
但是,可以使用最多兩層的屬性別名。
property alias color: rectangle.border.color
Rectangle {
id: rectangle
}
例如,下面是Button具有buttonText別名屬性的類型,該類型連接到Text子text對(duì)象的對(duì)象:
// Button.qml
import QtQuick 2.0
Rectangle {
property alias buttonText: textItem.text
width: 100; height: 30; color: "yellow"
Text { id: textItem }
}
以下代碼將為Button子Text對(duì)象創(chuàng)建一個(gè)具有定義的文本字符串的:
Button { buttonText: "Click Me" }
在這里,修改buttonText直接修改了textItem.text值;它不會(huì)更改其他值,然后更新textItem.text。如果buttonText不是別名,則更改其值實(shí)際上根本不會(huì)更改顯示的文本,因?yàn)閷傩越壎ú皇请p向的:buttonText如果更改了textItem.text,則值將已更改,但反之則沒有。
屬性別名的注意事項(xiàng)
僅在組件完全初始化后才能激活別名。當(dāng)引用未初始化的別名時(shí),將生成錯(cuò)誤。同樣,對(duì)別名屬性進(jìn)行別名也將導(dǎo)致錯(cuò)誤。
property alias widgetLabel: label
//will generate an error
//widgetLabel.text: "Initial text"
//will generate an error
//property alias widgetLabelText: widgetLabel.text
Component.onCompleted: widgetLabel.text = "Alias completed Initialization"
但是,當(dāng)在根對(duì)象中導(dǎo)入帶有屬性別名的QML對(duì)象類型時(shí),該屬性顯示為常規(guī)Qt屬性,因此可以在別名引用中使用。
別名屬性可能與現(xiàn)有屬性具有相同的名稱,從而有效覆蓋現(xiàn)有屬性。例如,以下QML類型具有color別名屬性,其名稱與內(nèi)置的Rectangle :: color屬性相同:
Rectangle {
id: coloredrectangle
property alias color: bluerectangle.color
color: "red"
Rectangle {
id: bluerectangle
color: "#1234ff"
}
Component.onCompleted: {
console.log (coloredrectangle.color) //prints "#1234ff"
setInternalColor()
console.log (coloredrectangle.color) //prints "#111111"
coloredrectangle.color = "#884646"
console.log (coloredrectangle.color) //prints #884646
}
//internal function that has access to internal properties
function setInternalColor() {
color = "#111111"
}
}
使用此類型并引用其color屬性的任何對(duì)象都將引用別名,而不是普通的Rectangle :: color屬性。但是,在內(nèi)部,矩形可以正確設(shè)置其color屬性并引用實(shí)際定義的屬性,而不是別名。
屬性別名和類型
屬性別名不能具有明確的類型規(guī)范。屬性別名的類型是其引用的屬性或?qū)ο蟮?em>聲明類型。因此,如果您為通過id引用的對(duì)象創(chuàng)建別名,并使用內(nèi)聯(lián)聲明的其他屬性,則無法通過別名訪問這些額外的屬性:
// MyItem.qml
Item {
property alias inner: innerItem
Item {
id: innerItem
property int extraProperty
}
}
您不能從此組件外部初始化inner.extraProperty,因?yàn)閕nner只是一個(gè)Item:
// main.qml
MyItem {
inner.extraProperty: 5 // fails
}
但是,如果您使用專用的.qml文件將內(nèi)部對(duì)象提取到單獨(dú)的組件中,則可以實(shí)例化該組件,并通過別名使用其所有屬性:
// MainItem.qml
Item {
// Now you can access inner.extraProperty, as inner is now an ExtraItem
property alias inner: innerItem
ExtraItem {
id: innerItem
}
}
// ExtraItem.qml
Item {
property int extraProperty
}
默認(rèn)屬性
對(duì)象定義可以具有一個(gè)默認(rèn)屬性。默認(rèn)屬性是如果在另一個(gè)對(duì)象的定義中聲明一個(gè)對(duì)象但未將其聲明為特定屬性的值的情況下,為其分配值的屬性。
使用optional default關(guān)鍵字聲明屬性會(huì)將其標(biāo)記為默認(rèn)屬性。例如,假設(shè)有一個(gè)具有默認(rèn)屬性的文件MyLabel.qml someText:
// MyLabel.qml
import QtQuick 2.0
Text {
default property var someText
text: "Hello, " + someText.text
}
該someText值可以在MyLabel對(duì)象定義中分配給它,如下所示:
MyLabel {
Text { text: "world!" }
}
與以下內(nèi)容完全相同:
MyLabel {
Text { text: "world!" }
}
但是,由于該someText屬性已被標(biāo)記為默認(rèn)屬性,因此無需將Text對(duì)象顯式分配給該屬性。
您會(huì)注意到,可以將子對(duì)象添加到任何基于Item的類型,而無需將其顯式添加到children屬性。這是因?yàn)槟J(rèn)的屬性項(xiàng)目是其data財(cái)產(chǎn),并添加到此列表中的任何項(xiàng)目項(xiàng)目會(huì)自動(dòng)添加到其列表中的孩子。
默認(rèn)屬性對(duì)于重新分配項(xiàng)目的子項(xiàng)很有用。請(qǐng)參見TabWidget示例,該示例使用默認(rèn)屬性自動(dòng)將TabWidget的子級(jí)重新分配為內(nèi)部ListView的子級(jí)。另請(qǐng)參見擴(kuò)展QML。
只讀屬性
對(duì)象聲明可以使用readonly關(guān)鍵字通過以下語法定義只讀屬性:
readonly property <propertyType> <propertyName> : <initialValue>
初始化時(shí)必須為只讀屬性分配一個(gè)值。初始化只讀屬性后,無論是從命令式代碼還是其他方式,都不再可以為其賦予值。
例如,Component.onCompleted以下塊中的代碼無效:
Item {
readonly property int someNumber: 10
Component.onCompleted: someNumber = 20
// doesn't work, causes an error
}
注意:只讀屬性也不能是默認(rèn)屬性。
屬性修改器對(duì)象
屬性可以具有與其關(guān)聯(lián)的屬性值修改器對(duì)象。聲明與特定屬性關(guān)聯(lián)的屬性修飾符類型的實(shí)例的語法如下:
<PropertyModifierTypeName> on <propertyName> {
// attributes of the object instance
}
重要的是要注意,以上語法實(shí)際上是一個(gè)對(duì)象聲明,它將實(shí)例化作用于預(yù)先存在的屬性的對(duì)象。
某些屬性修飾符類型可能僅適用于特定的屬性類型,但這不是語言所強(qiáng)制執(zhí)行的。例如,所NumberAnimation提供的類型QtQuick將僅對(duì)數(shù)字類型的屬性(例如int或real)進(jìn)行動(dòng)畫處理。嘗試使用NumberAnimation具有非數(shù)字屬性的不會(huì)導(dǎo)致錯(cuò)誤,但是不會(huì)為非數(shù)字屬性設(shè)置動(dòng)畫。屬性修改器類型與特定屬性類型相關(guān)聯(lián)時(shí)的行為由其實(shí)現(xiàn)方式定義。
信號(hào)屬性
信號(hào)是來自某個(gè)對(duì)象的通知,表明發(fā)生了某些事件:例如,屬性已更改,動(dòng)畫已開始或停止或下載圖像時(shí)。在鼠標(biāo)區(qū)域類型,例如,有一個(gè)被點(diǎn)擊時(shí)發(fā)射當(dāng)鼠標(biāo)區(qū)域內(nèi)的用戶點(diǎn)擊信號(hào)。
每當(dāng)發(fā)出特定信號(hào)時(shí),可以通過信號(hào)處理程序通知對(duì)象。使用on <Signal>語法聲明信號(hào)處理程序,其中<Signal>是信號(hào)名稱,首字母大寫。必須在發(fā)出信號(hào)的對(duì)象的定義內(nèi)聲明信號(hào)處理程序,并且該處理程序應(yīng)包含在調(diào)用信號(hào)處理程序時(shí)要執(zhí)行的JavaScript代碼塊。
例如,下面的onClicked信號(hào)處理程序在MouseArea對(duì)象定義中聲明,并在單擊MouseArea時(shí)被調(diào)用,從而導(dǎo)致控制臺(tái)消息被打?。?/p>
import QtQuick 2.0
Item {
width: 100; height: 100
MouseArea {
anchors.fill: parent
onClicked: {
console.log("Click!")
}
}
}
定義信號(hào)屬性
通過注冊(cè)一個(gè)類的Q_SIGNAL,然后在QML類型系統(tǒng)中注冊(cè),可以為C ++中的類型定義一個(gè)信號(hào)。或者,可以使用以下語法在QML文檔的對(duì)象聲明中定義對(duì)象類型的自定義信號(hào):
signal <signalName>[([<type> <parameter name>[, ...]])]
試圖在同一類型塊中聲明兩個(gè)具有相同名稱的信號(hào)或方法是錯(cuò)誤的。但是,新信號(hào)可能會(huì)在類型上重復(fù)使用現(xiàn)有信號(hào)的名稱。(這應(yīng)該謹(jǐn)慎行事,因?yàn)楝F(xiàn)有信號(hào)可能會(huì)被隱藏并變得難以訪問。)
這是信號(hào)聲明的三個(gè)示例:
import QtQuick 2.0
Item {
signal clicked
signal hovered()
signal actionPerformed(string action, var actionResult)
}
如果信號(hào)沒有參數(shù),則“()”括號(hào)是可選的。如果使用了參數(shù),則必須聲明參數(shù)類型,如上述信號(hào)的string和var參數(shù)一樣actionPerformed。允許的參數(shù)類型與此頁面上的“ 定義屬性屬性”下列出的參數(shù)類型相同。
要發(fā)出信號(hào),請(qǐng)將其作為方法調(diào)用。發(fā)出信號(hào)時(shí),將調(diào)用任何相關(guān)的信號(hào)處理程序,并且處理程序可以使用定義的信號(hào)參數(shù)名稱來訪問相應(yīng)的參數(shù)。
屬性更改信號(hào)
QML類型還提供了內(nèi)置的屬性更改信號(hào),每當(dāng)屬性值更改時(shí)都會(huì)發(fā)出該信號(hào),如先前在屬性屬性部分中所述。有關(guān)這些信號(hào)為何有用以及如何使用它們的更多信息,請(qǐng)參見即將到來的關(guān)于屬性更改信號(hào)處理程序的部分。
信號(hào)處理程序?qū)傩?a target="_blank">
信號(hào)處理程序是一種特殊的方法屬性,只要發(fā)出關(guān)聯(lián)的信號(hào),QML引擎就會(huì)調(diào)用該方法的實(shí)現(xiàn)。在QML中向?qū)ο蠖x添加信號(hào)將自動(dòng)向該對(duì)象定義添加關(guān)聯(lián)的信號(hào)處理程序,該信號(hào)處理程序默認(rèn)情況下為空實(shí)現(xiàn)??蛻艨梢蕴峁┮环N實(shí)現(xiàn),以實(shí)現(xiàn)程序邏輯。
考慮以下SquareButton類型,其定義在SquareButton.qml文件中提供,如下所示,并帶有信號(hào)activated和deactivated:
// SquareButton.qml
Rectangle {
id: root
signal activated(real xPosition, real yPosition)
signal deactivated
property int side: 100
width: side; height: side
MouseArea {
anchors.fill: parent
onPressed: root.activated(mouse.x, mouse.y)
onReleased: root.deactivated()
}
}
這些信號(hào)可由SquareButton同一目錄中另一個(gè)QML文件中的任何對(duì)象接收,其中信號(hào)處理程序的實(shí)現(xiàn)由客戶端提供:
// myapplication.qml
SquareButton {
onActivated: console.log("Activated at " + xPosition + "," + yPosition)
onDeactivated: console.log("Deactivated!")
}
有關(guān)信號(hào)使用的更多詳細(xì)信息,請(qǐng)參見信號(hào)和處理程序事件系統(tǒng)。
屬性更改信號(hào)處理程序
屬性更改信號(hào)的信號(hào)處理程序采用on <Property> Changed的語法形式,其中<Property>是屬性的名稱,首字母大寫。例如,盡管TextInput類型文檔沒有記錄textChanged信號(hào),但由于TextInput具有text屬性,因此該信號(hào)是隱式可用的,因此onTextChanged只要此屬性發(fā)生更改,就可以編寫要調(diào)用的信號(hào)處理程序:
import QtQuick 2.0
TextInput {
text: "Change this!"
onTextChanged: console.log("Text has changed to:", text)
}
方法屬性
對(duì)象類型的方法是可以調(diào)用以執(zhí)行某些處理或觸發(fā)其他事件的功能??梢詫⒁环N方法連接到信號(hào),以便在發(fā)出信號(hào)時(shí)自動(dòng)調(diào)用該方法。有關(guān)更多詳細(xì)信息,請(qǐng)參見信號(hào)和處理程序事件系統(tǒng)。
定義方法屬性
可以通過在C ++中為類型定義一種方法,方法是:標(biāo)記一個(gè)類的函數(shù),然后使用Q_INVOKABLE在QML類型系統(tǒng)中注冊(cè)該類,或者將其注冊(cè)為該類的Q_SLOT?;蛘?,可以使用以下語法將自定義方法添加到QML文檔中的對(duì)象聲明中:
function <functionName>([<parameterName>[, ...]]) { <body> }
可以將方法添加到QML類型,以定義獨(dú)立的可重用的JavaScript代碼塊。這些方法可以在內(nèi)部或外部對(duì)象中調(diào)用。
與信號(hào)不同,方法參數(shù)類型不必聲明,因?yàn)樗鼈兡J(rèn)為var類型。
試圖在同一類型塊中聲明兩個(gè)具有相同名稱的方法或信號(hào)是錯(cuò)誤的。但是,新方法可以在類型上重用現(xiàn)有方法的名稱。(這應(yīng)該謹(jǐn)慎行事,因?yàn)楝F(xiàn)有方法可能會(huì)被隱藏并且變得無法訪問。)
下面是一個(gè)帶有分配值時(shí)調(diào)用的方法的Rectangle:calculateHeight()``height
import QtQuick 2.0
Rectangle {
id: rect function calculateHeight() {
return rect.width / 2;
}
width: 100
height: calculateHeight()
}
如果該方法具有參數(shù),則可以在方法內(nèi)按名稱訪問它們。在下面,當(dāng)單擊MouseArea時(shí),它會(huì)調(diào)用該moveTo()方法,然后該方法可以引用接收newX到的newY參數(shù)和參數(shù)來重新放置文本:
import QtQuick 2.0
Item {
width: 200; height: 200
MouseArea {
anchors.fill: parent
onClicked: label.moveTo(mouse.x, mouse.y)
}
Text {
id: label
function moveTo(newX, newY) {
label.x = newX;
label.y = newY;
}
text: "Move me!"
}
}
附加屬性和附加信號(hào)處理程序
附加屬性和附加信號(hào)處理程序是使對(duì)象能夠使用其他屬性或信號(hào)處理程序進(jìn)行注釋的機(jī)制,而附加屬性或信號(hào)處理程序?qū)τ谠搶?duì)象是不可用的。特別是,它們?cè)试S對(duì)象訪問與單個(gè)對(duì)象特別相關(guān)的屬性或信號(hào)。
QML類型實(shí)現(xiàn)可以選擇在C ++中創(chuàng)建具有特定屬性和信號(hào)的附加類型。然后可以創(chuàng)建這種類型的實(shí)例,并在運(yùn)行時(shí)將其附加到特定對(duì)象,從而允許那些對(duì)象訪問附加類型的屬性和信號(hào)。通過為屬性和相應(yīng)的信號(hào)處理程序添加前綴附加類型的名稱來訪問它們。
對(duì)附加屬性和處理程序的引用采用以下語法形式:
<AttachingType>.<propertyName>
<AttachingType>.on<SignalName>
例如,ListView的類型有一個(gè)附加屬性ListView.isCurrentItem,可用于在每個(gè)委托對(duì)象的ListView。每個(gè)單獨(dú)的委托對(duì)象都可以使用它來確定它是否是視圖中當(dāng)前選中的項(xiàng)目:
import QtQuick 2.0
ListView {
width: 240; height: 320
model: 3 delegate: Rectangle {
width: 100; height: 30
color: ListView.isCurrentItem ? "red" : "yellow"
}
}
在這種情況下,附加類型的名稱為ListView,相關(guān)屬性為isCurrentItem,因此附加屬性稱為ListView.isCurrentItem。
附加的信號(hào)處理程序以相同的方式引用。例如,組件的創(chuàng)建過程完成后,通常使用Component.onCompleted附加信號(hào)處理程序來執(zhí)行一些JavaScript代碼。在下面的示例中,一旦完全創(chuàng)建ListModel,Component.onCompleted將自動(dòng)調(diào)用其信號(hào)處理程序以填充模型:
import QtQuick 2.0
ListView {
width: 240; height: 320
model: ListModel {
id: listModel
Component.onCompleted: {
for (var i = 0; i < 10; i++)
listModel.append({"Name": "Item " + i})
}
}
delegate: Text { text: index }
}
由于附加類型的名稱為Component并且該類型具有完整的信號(hào),因此附加信號(hào)處理程序稱為Component.onCompleted。
有關(guān)訪問附加屬性和信號(hào)處理程序的注釋
一個(gè)常見的錯(cuò)誤是假定附加屬性和信號(hào)處理程序可從已附加這些屬性的對(duì)象的子級(jí)直接訪問。不是這種情況。附加類型的實(shí)例僅附加到特定對(duì)象,而不附加到對(duì)象及其所有子對(duì)象。
例如,下面是包含附件屬性的先前示例的修改版本。這次,委托是項(xiàng)目,而彩色矩形是該項(xiàng)目的子項(xiàng):
import QtQuick 2.0
ListView {
width: 240; height: 320
model: 3
delegate: Item {
width: 100; height: 30
Rectangle {
width: 100; height: 30
color: ListView.isCurrentItem ? "red" : "yellow" // WRONG! This won't work.
}
}
}
這不能按預(yù)期方式工作,因?yàn)?code>ListView.isCurrentItem它僅附加在根委托對(duì)象上,而不附加在其子對(duì)象上。由于Rectangle是委托的子代,而不是委托本身,因此它不能以形式訪問isCurrentItem附加屬性ListView.isCurrentItem。因此,矩形應(yīng)isCurrentItem通過根委托進(jìn)行訪問:
ListView {
//....
delegate: Item {
id: delegateItem
width: 100; height: 30
Rectangle {
width: 100; height: 30
color: delegateItem.ListView.isCurrentItem ? "red" : "yellow" // correct
}
}
}
現(xiàn)在,delegateItem.ListView.isCurrentItem正確引用isCurrentItem委托的附加屬性。
枚舉屬性(Enumeration Attributes)
枚舉提供了一組固定的命名選項(xiàng)??梢允褂?code>enum關(guān)鍵字在QML中聲明它們:
// MyText.qml
Text {
enum TextType {
Normal, Heading
}
}
如上所示,枚舉類型(例如TextType)和值(例如Normal)必須以大寫字母開頭。
通過<Type>.<EnumerationType>.<Value>或引用值<Type>.<Value>。
// MyText.qml
Text {
enum TextType {
Normal,
Heading
}
property int textType: MyText.TextType.Normal
font.bold: textType == MyText.TextType.Heading
font.pixelSize: textType == MyText.TextType.Heading ? 24 : 12
}
有關(guān)QML中枚舉用法的更多信息,請(qǐng)參見QML基本類型 枚舉文檔。
Qt 5.10中引入了在QML中聲明枚舉的功能。