QtQuick QML 快速上手教程-3 QML 對象屬性

 

QML對象類型屬性類型集如下:

  • id 屬性
  • 普通屬性
  • 信號屬性
  • 信號處理程序屬性
  • 方法屬性
  • 附加屬性和附加信號處理程序屬性

這些屬性將在下面詳細討論.

id 屬性

每種QML對象類型都只有一個屬性. 此屬性由語言本身提供,並且不能由任何QML對象類型重新定義或覆蓋.

可以將值分配給對象實例的屬性,以允許該對象被其他對象標識和引用. 此id必須以小寫字母或下劃線開頭,並且不能包含字母,數字和下劃線以外的字符.

下面是一個TextInput對象和一個Text對象. TextInput對象的id值設置爲" myTextInput". 通過引用myTextInput.text , Text對象將其text屬性設置爲與TextInputtext屬性具有相同的值. 現在,兩個項目將顯示相同的文本:

import QtQuick 2.0

Column {
    width: 200; height: 200

    TextInput { id: myTextInput; text: "Hello World" }

    Text { text: myTextInput.text }
}

可以在聲明對象的內的任何位置通過其id引用對象. 因此, id值在其組件範圍內必須始終是唯一的. 

創建對象實例後,無法更改其屬性的值. 雖然它可能看起來像一個普通的屬性,id屬性不是一個普通的property屬性; 例如,在上面的示例中無法訪問myTextInput.id

Property Attributes (普通屬性)

屬性是可以分配靜態值或綁定到動態表達式的對象的屬性. 一個屬性的值可以被其他對象讀取. 通常,它也可以由另一個對象修改,除非特定的QML類型明確禁止特定屬性使用.

通過註冊類的Q_PROPERTY ,然後再向QML類型系統註冊,可以在C ++中爲類型定義屬性. 或者,可以使用以下語法在QML文檔的對象聲明中定義對象類型的自定義屬性:

Rectangle {
    property color previousColor
    property color nextColor
    onNextColorChanged: console.log("The next color will be: " + nextColor.toString())
}

屬性名稱必須以小寫字母開頭,並且只能包含字母,數字和下劃線. JavaScript保留字不是有效的屬性名稱. 

除了枚舉類型外,任何QML基本類型都可以用作自定義屬性類型,例如

Item {
    property int someNumber
    property string someString
    property url someUrl
}

此外,任何QML對象類型都可以用作屬性類型. 例如:

property Item someItem
property Rectangle someRectangle

爲屬性屬性賦值

可以通過兩種不同的方式指定對象實例的屬性值:

  • 初始化時
  • 需要的時候賦值

在初始化時爲屬性分配值的語法是:

<propertyName> : <value>

如果需要,可以將初始化值分配與對象聲明中的屬性定義組合. 在這種情況下,屬性定義的語法變爲:

property <propertyType> <propertyName> : <value>

屬性值初始化的示例如下:

import QtQuick 2.0

Rectangle {
    color: "red"
    property color nextColor: "blue" // combined property declaration and initialization
}

需要的時候賦值

import QtQuick 2.0

Rectangle {
    id: rect
    Component.onCompleted: {
        rect.color = "red"
    }
}

以下示例,顯示了兩種方法給屬性賦值:

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
    }
}

屬性安全問題

就像c++一樣,int 類型不能賦值string,QML裏也一樣只能爲屬性分配與屬性類型匹配的值

例如,如果一個屬性是一個實數,並且如果您嘗試爲其分配一個字符串,則會出現錯誤:

property int volume: "four"  // generates an error; the property's object will not be loaded

同樣,如果在運行時爲屬性分配了錯誤類型的值,則不會分配新值,並且會生成錯誤.

可以爲列表類型屬性分配QML對象類型值的列表. 定義對象列表值的語法是用方括號括起來的逗號分隔列表:

例如, Item類型具有一個states屬性,該屬性用於保存State類型對象的列表. 下面的代碼將該屬性的值初始化爲三個State對象的列表:

import QtQuick 2.0

Item {
    states: [
        State { name: "loading" },
        State { name: "running" },
        State { name: "stopped" }
    ]
}

如果列表包含單個項目,則可以省略方括號:

import QtQuick 2.0

Item {
    states: State { name: "running" }
}

可以使用以下語法在對象聲明中指定列表類型屬性:

property list<<objectType>> propertyName

//或者
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"}
    ]
}

如果希望聲明一個屬性來存儲不一定是QML對象類型值的值列表,則應該聲明一個var屬性.

 

Signal Attributes  信號屬性

信號是來自某個對象的通知,表明發生了某些事件:例如,屬性已更改,動畫已開始或停止或下載圖像時. 例如, MouseArea類型具有單擊信號,當用戶在鼠標區域內單擊時發出該信號.

每當發出特定信號時,可以通過信號處理程序通知對象. where is the name of the signal, with the first letter capitalized. 使用語法聲明信號處理程序,其中是名稱,首字母大寫. 必須在發出信號的對象的定義內聲明信號處理程序,並且該處理程序應包含在調用信號處理程序時要執行的JavaScript代碼塊.

例如,下面的信號處理程序在MouseArea對象定義中聲明,並在單擊MouseArea時被調用,從而導致控制檯消息被打印:

import QtQuick 2.0

Item {
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log("Click!")
        }
    }
}

通過註冊一個類的Q_SIGNAL ,然後在QML類型系統中註冊,可以爲C ++中的類型定義一個信號. 或者,可以使用以下語法在QML文檔的對象聲明中定義對象類型的自定義信號:

signal <signalName>[([<type> <parameter name>[, ...]])]

試圖在同一類型塊中聲明兩個具有相同名稱的信號或方法是錯誤的. 但是,新信號可能會在類型上重複使用現有信號的名稱. (這應該謹慎行事,因爲現有信號可能會被隱藏並變得難以訪問.)

這是信號聲明的三個示例:

import QtQuick 2.0

Item {
    signal clicked
    signal hovered()
    signal actionPerformed(string action, var actionResult)
}

如果信號沒有參數,則"()"括號是可選的. 如果使用了參數,則必須聲明參數類型,就像上述actionPerformed信號的stringvar參數一樣. 允許的參數類型與此頁面上的" 定義屬性屬性"下列出的參數類型相同.

要發出信號,請將其作爲方法調用. 發出信號時,將調用任何相關的信號處理程序 ,並且處理程序可以使用定義的信號參數名稱來訪問相應的參數.

 

屬性改變信號

QML類型還提供了內置的 ,每當屬性值更改時都會發出該 ,如先前在屬性屬性部分中所述. QML屬性的值更改時,會自動發出信號.格式是on<Signal> 這種形式。

import QtQuick 2.0

Rectangle {
    id: rect
    width: 100; height: 100

    MouseArea {
        anchors.fill: parent
        onPressedChanged: {
            console.log("Mouse area is pressed?", pressed)
        }
    }
}

在上面示例中MouseArea觸發pressedChanged信號。我們捕捉這個信號就用onPressedChanged就可以了 ,沒錯,首部加on,信號首字母變爲大寫就可以了!

即使MouseArea文檔沒有記錄名爲onPressedChanged的信號處理程序,該信號onPressedChangedpressed屬性存在的事實隱式提供.

Using the Connections Type

在某些情況下,可能希望訪問發出該信號的對象之外的信號. 爲此, QtQuick模塊提供了Connections類型,用於連接到任意對象的信號. Connections對象可以從其指定的目標接收任何信號.

例如, onClicked在前面的示例中的處理程序可能已被由所述根接收矩形代替,通過將onClicked處理程序在一個連接對象,該對象具有其目標設定到鼠標區域 :

import QtQuick 2.0

Rectangle {
    id: rect
    width: 100; height: 100

    MouseArea {
        id: mouseArea
        anchors.fill: parent
    }

    Connections {
        target: mouseArea
        onClicked: {
            rect.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1);
        }
    }
}

簡單的介紹下qml信號,會具體一章來講qml的信號和槽,並且會有詳細的示例代碼。還有c++與qml的信號傳遞與一些好用的技巧分享。

 

Attributes 方法屬性

可以通過在C ++中爲類型定義一種方法,方法是標記一個類的功能,然後用Q_INVOKABLE在QML類型系統中註冊該類,或者將其註冊爲該類的Q_SLOT . 或者,可以使用以下語法將自定義方法添加到QML文檔中的對象聲明中:

function <functionName>([<parameterName>[, ...]]) { <body> }

可以將方法添加到QML類型,以定義獨立的可重用的JavaScript代碼塊. 這些方法可以在內部或外部對象中調用.

與信號不同,方法參數類型不必聲明,因爲它們默認爲var類型.

下面是一個帶有calculateHeight()方法的矩形 ,該矩形在分配height值時被調用:

import QtQuick 2.0
Rectangle {
    id: rect

    function calculateHeight() {
        return rect.width / 2;
    }

    width: 100
    height: calculateHeight()
}

如果該方法具有參數,則可以在方法內按名稱訪問它們. 在下面,當單擊MouseArea時,它將調用moveTo()方法,該方法然後可以引用接收到的newXnewY參數來重新newY文本:

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!"
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章