組件聲明以及設置屬性
所有的組件的基類為:QtObject,在c++中名稱為:QObject。
在qml和c++名稱有所區別,例如在Qml中QtObject,在C++會省略一個t(QObject)
聲明組件的方式:
組件名 {屬性名:值}
在實際應用中:
import QtQuickWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")//聲明Text組件Text{text:"Text組件"}
}
組件屬性類型:
- id屬性
- 枚舉屬性
- 自定義屬性
- 組件屬性
- JavaScript方法
- 信號屬性
- 信號處理程序
- 附加屬性和附加信號處理程序
id屬性
Qml 組件只能擁有一個 id 屬性,可以用于數據的綁定。
import QtQuick
import QtQuick.LayoutsWindow {id: windowwidth: 400height: 300visible: truetitle: qsTr("Hello World")
}
給窗口的id屬性賦予window。
枚舉屬性
枚舉提供一組固定的命名選擇。可以在 Qml 中使用關鍵字聲明: enum
Text {enum TextType {Normal,Heading}
}
自定義屬性
在組件中自行定義的屬性稱為自定義屬性或者擴展屬性,自定義屬性名稱必須以小寫字母開頭,并且只能包含字母、數字和下劃線。
[default] [required] [readonly] property <propertyType> <propertyName>
default 默認屬性
組件可以擁有一個默認屬性(僅一個)。默認屬性是一種非常實用的特性,它允許組件在實例化時,將未明確指定屬性名的子元素自動關聯到該默認屬性,從而簡化代碼編寫。
使用可選關鍵字 default 聲明屬性會將其標記為默認屬性
default property <propertyType> <propertyName>
default property 屬性類型 屬性名
示例:
// 自定義組件 MyComponent.qml
Item {// 聲明默認屬性,類型為Item(可以是任意類型)default property Item content// 使用默認屬性Component.onCompleted: {console.log("默認屬性內容:", content)}
}
MyComponent {// 這里的Text沒有指定屬性名,會自動賦值給contentText { text: "這會成為默認屬性的值" }
}
聲明MyComponent 組件,并賦予子組件Text 給MyComponent ,Text 組件會自行存儲到content默認屬性中。
上面的代碼等價于:
MyComponent {content: Text { text: "這會成為默認屬性的值" }
}
常見使用場景
1. 容器類組件(最典型用法)
Qt 自帶的 Column 、 Row 、 ListView 等容器組件都使用了默認屬性,讓子元素的添加更自然:
Column {// 這些Text會自動添加到Column的默認屬性children中Text { text: "Item 1" }Text { text: "Item 2" }
}
( Column 的默認屬性實際是 children ,用于存儲子元素列表)
2. 自定義容器組件
// Card.qml - 卡片組件
Rectangle {color: "white"border.width: 1radius: 4// 聲明默認屬性,用于接收卡片內容default property Item cardContent// 布局默認屬性內容Column {anchors.fill: parentanchors.margins: 10// 顯示默認屬性內容Loader { sourceComponent: cardContent }}
}// 使用Card組件
Card {// 這里的內容會自動成為cardContentText { text: "卡片標題" }Text { text: "卡片內容..." }
}
3. 處理列表類型的默認屬性
默認屬性也可以是列表類型,用于接收多個子元素:
Item {// 聲明列表類型的默認屬性default property list<Item> itemsColumn {// 顯示所有默認屬性中的元素Repeater {model: itemsdelegate: Loader { sourceComponent: modelData }}}
}
// 使用時可以直接添加多個子元素
MyList {Text { text: "第一個元素" }Text { text: "第二個元素" }Text { text: "第三個元素" }
}
注意事項
- 一個組件只能有一個默認屬性
- 默認屬性可以是任意類型(基本類型、對象、列表等)
- 如果同時存在顯式賦值和默認賦值,顯式賦值會覆蓋默認賦值
- 通常用于容器類組件,但也可用于需要簡化賦值的任何場景
required 必填屬性
定義一個不可為空的屬性,簡稱必填屬性。
required property <propertyType> <propertyName>
required property 屬性類型 屬性名
示例:
// 自定義組件 UserCard.qml
Rectangle {// 聲明必填屬性(姓名和年齡為必需)required property string userNamerequired property int userAge// 使用這些屬性Text {text: `姓名: ${userName}, 年齡: ${userAge}`anchors.centerIn: parent}
}
使用帶必填屬性的組件:
// 正確用法:提供了所有必填屬性
UserCard {userName: "張三"userAge: 30width: 200height: 80
}// 錯誤用法:缺少必填屬性(會拋出運行時錯誤)
UserCard {// 缺少 userName 和 userAge,QML引擎會報錯width: 200height: 80
}
readonly 只讀屬性
required對象聲明可以使用關鍵字定義只讀屬性,語法如下:readonly
readonly property <propertyType> <propertyName> : <value>
readonly property 屬性類型 屬性名 : 值
組件屬性
不同的組件具有不同的屬性。例如:Text組件的text屬性控制界面顯示的文本內容。
在Qml中所有的組件都基于QtObject,QtObject卻僅有一個屬性(objectName),在使用組件時必須了解組件的繼承關系。
因為所有組件都是基于QtObject,所以組件都擁有QtObject的objectName屬性。
Text組件的繼承關系:QtObject->Item->Text
JavaScript方法
JavaScript方法是可以調用該函數來執行某些處理或觸發進一步的事件。
function <functionName>([<parameterName>[: <parameterType>][, ...]]) [: <returnType>] { <body> }
//不帶參數
function 方法名():返回類型{語句塊}//帶參數
function 方法名(參數名:參數類型){語句塊}//帶參數,帶返回值
function 方法名(參數名:參數類型):返回類型{語句塊}
示例:
import QtQuick
Rectangle {id: rectfunction calculateHeight(): real {return rect.width / 2;}width: 100height: calculateHeight()
}
信號屬性以及信號處理程序
在 Qml 中,信號(Signal)是組件間通信的核心機制,允許一個組件在特定事件發生時發出通知,其他組件可以 “連接”(connect)到這個信號并做出響應。信號本身不是傳統意義上的 “屬性”,但可以理解為組件對外暴露的一種 “事件接口”,用于觸發外部邏輯。
信號的本質
- 信號是組件定義的 “事件觸發器”,當特定條件滿足時(如按鈕被點擊、數據變化等)會被 “發射” 信號
- 其他組件可以通過 “信號處理程序”(Signal Handler)或代碼連接來響應信號
- 信號可以攜帶參數,用于傳遞事件相關的數據
使用 signal 關鍵字聲明信號:
// 自定義組件 MyButton.qml
Rectangle {id: rootwidth: 100height: 30color: "lightblue"// 聲明一個無參信號signal clicked// 聲明一個帶參數的信號signal textChanged(string newText, string oldText)Text {id: labelanchors.centerIn: parenttext: "Click Me"}MouseArea {anchors.fill: parentonClicked: {// 發射信號(觸發事件)root.clicked()root.textChanged("Clicked!", label.text)}}
}
示例代碼中, MouseArea 是 Qt Quick 提供的一個內置組件,專門用于處理鼠標和觸摸事件。
信號處理程序
使用組件時,通過 on 語法定義信號處理器(首字母大寫):
MyButton {// 響應無參信號onClicked: {console.log("按鈕被點擊了!")}// 響應帶參數的信號onTextChanged: {console.log(`文本從 ${oldText} 變為 ${newText}`)}
}
動態響應信號
也可以在 JavaScript 中動態連接信號與處理函數。
MyButton {id: myBtnComponent.onCompleted: {// 動態連接信號myBtn.clicked.connect(handleClick)myBtn.textChanged.connect(handleTextChange)}function handleClick() {console.log("動態連接:按鈕被點擊")}function handleTextChange(newText, oldText) {console.log(`動態連接:文本變化 ${oldText} -> ${newText}`)}
}
信號與屬性的關聯
雖然信號不是屬性,但 QML 的屬性系統會自動為屬性生成 “變化信號”(Change Signal):
- 當屬性值發生變化時,會自動發射 onChanged 信號
- 例如 property string name 會自動生成 onNameChanged 信號
Item {property string userName: "默認名稱"// 響應屬性變化信號(自動生成)onUserNameChanged: {console.log(`用戶名變為:${userName}`)}Button {text: "修改名稱"onClicked: userName = "新名稱" // 修改屬性會觸發信號}
}
核心特點
- 松耦合通信:信號發射方不需要知道誰在接收,接收方也不需要知道信號來源
- 多連接支持:一個信號可以連接多個處理函數
- 參數傳遞:通過信號參數傳遞數據,靈活傳遞事件上下文
- 自動生成:屬性自動生成變化信號,簡化狀態監聽
信號是 QML 中實現組件交互、狀態管理的核心機制,廣泛用于 UI 交互(如按鈕點擊、列表項選擇)、數據流轉(如模型更新通知)等場景
附加信號屬性以及附加信號處理程序
在 QML 中,附加屬性(Attached Properties)是一種特殊的屬性機制,允許一個組件為另一個組件添加額外的屬性,而無需修改被添加組件的原始定義。這些屬性由一個 “附加類型” 提供,通過 <附加類型>.<屬性名> 的語法使用。
附加屬性的核心作用是:在不侵入組件內部實現的前提下,為其添加特定場景下的額外功能或數據。
基本用法與示例
最常見的附加屬性來自 Qt Quick 的內置類型,例如 Item 的 Layout 附加屬性(用于布局)、 Component 的 ApplicationWindow 附加屬性等。
示例1:
在 Row 、 Column 等布局中, Layout 附加類型為子元素提供布局相關的附加屬性:
import QtQuick 2.15
import QtQuick.Layouts 1.15Row {spacing: 10Rectangle {color: "red"width: 50height: 50// Layout.alignment 是附加屬性,控制在布局中的對齊方式Layout.alignment: Qt.AlignCenter}Rectangle {color: "blue"width: 50height: 80// Layout.fillHeight 是附加屬性,控制是否填充布局高度Layout.fillHeight: true}
}
這里 Layout.alignment 和 Layout.fillHeight 并非 Rectangle 自身的屬性,而是 Layout 類型為 Rectangle 附加的布局屬性。
示例2:
Window 類型提供的附加屬性可用于控制子元素在窗口中的行為:
import QtQuick 2.15
import QtQuick.Controls 2.15ApplicationWindow {id: mainWindowwidth: 400height: 300title: "附加屬性示例"Text {// Window.title 是附加屬性,綁定到窗口標題text: "當前窗口標題: " + Window.title// Window.visibility 是附加屬性,反映窗口可見性狀態onWindowVisibilityChanged: {console.log("窗口可見性變化: ", Window.visibility)}}
}
附加屬性的工作原理
- 定義一個 “附加類型”(通常是一個 QML 類型或 C++ 注冊的類型)
- 該類型提供 attachedProp erties ,用于為其他組件附加屬性
- 使用時通過 <附加類型>.<屬性名> 的語法訪問,QML 引擎會自動關聯到目標組件
代碼編寫規范(建議)
qml的組件聲明規范(使用text組件示例):
Text {id:text1 //聲明組件ID(唯一)//可選,枚舉類型enum TextType {Normal,Heading}//可選,聲明自定義屬性,(屬性名首字母必須小寫)property string label//可選,聲明javascript 方法function calculateHeight(): real {return text1 .width / 5;}//設置外觀屬性width:100 //聲明寬度height:calculateHeight() //聲明高度anchors.verticalCenter: parent.verticalCenter //可選,錨點(anchors)布局設置//聲明組件的內容屬性text:"Text組件"//聲明信號(信號用于組件的通知,表示某些事件已經發生)signal clicked //聲明信號處理程序MouseArea {anchors.fill: parent }
}
組件屬性賦予順序 :
- id屬性
- 枚舉屬性
- 自定義屬性
- 組件屬性
- JavaScript方法
- 信號屬性
- 信號處理程序
- 附加屬性和附加信號處理程序
以上的屬性編寫順序是為之后方便閱讀。(沒有硬性要求,只為方便查看)