一、概念
在QML
中,Delegate
是一種非常重要的組件,特別是在使用ListView
、GridView
、PathView
等視圖組件時。Delegate用于定義每個列表或網格中的項目是如何展示的。通過自定義Delegate,你可以控制每個項目的外觀和行為。
Delegate
通常是一個自定義的Item
或Component
,它定義了如何在列表或網格中顯示每個項目。例如,你可以在Delegate中定義文本標簽、圖片、按鈕等。
二、常用委托控件
常用委托控件:ItemDelegate、CheckDelegate、RadioDelegate、SwitchDelegate和SwipeDelegate。
1.?ItemDelegate?
屬性/信號/方法 | 類型 | 說明 | 示例 |
---|---|---|---|
?highlighted? | bool | 當前項高亮狀態,常用于列表選中項 | highlighted: ListView.isCurrentItem |
?text? | string | 顯示的主文本內容 | text: model.name |
?icon? | var | 左側圖標資源(QtQuick.Icon類型) | icon.source: "icon.png" |
?spacing? | real | 圖標與文本間距(像素) | spacing: 10 |
?padding? | real | 內容區域內邊距 | padding: 12 |
?onClicked? | signal | 點擊時觸發 | onClicked: console.log(index) |
?background? | Component | 自定義背景組件 | background: Rectangle{color:"red"} |
代碼示例:
//ItemDelegateListView {id: listViewItemx: 0; y: 0width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: ItemDelegate {text: modelDatawidth: listViewItem.widthicon.source:"qrc:/image/user.png"icon.color: "transparent"//icon.name: "edit-cut"display: AbstractButton.TextBesideIconhighlighted: ListView.isCurrentItemonClicked: {listViewItem.currentIndex = index;console.log("clicked:", modelData)}}}
運行結果:
2.CheckDelegate
屬性/信號/方法 | 類型 | 說明 | 示例 |
---|---|---|---|
?checkState? | enum | 三態狀態(Checked/Unchecked/PartiallyChecked) | checkState: Qt.Checked |
?tristate? | bool | 是否啟用三態模式 | tristate: true |
?checked? | bool | 當前選中狀態 | checked: model.selected |
?onToggled? | signal | 狀態變化時觸發 | onToggled: model.checked=checked |
?indicator? | Component | 自定義復選框樣式 | indicator: Rectangle{...} |
?nextCheckState? | method | 控制點擊時的狀態切換邏輯 | function nextCheckState(){...} |
代碼示例:
//CheckDelegateproperty var selectedItems: []ListView {id: listViewCheckx: 320; y: 0width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: CheckDelegate {text: modelDatawidth: listViewCheck.widthonCheckedChanged: {if (checked) {selectedItems.push(modelData)} else {selectedItems = selectedItems.filter(item => item !== modelData)}}}}Button {text: "Selected Items"anchors.bottom: listViewCheck.bottomanchors.horizontalCenter: listViewCheck.horizontalCenteronClicked: {console.log("Selected items:", selectedItems)}}
運行結果:
3.RadioDelegate
屬性/信號/方法 | 類型 | 說明 | 示例 |
---|---|---|---|
?autoExclusive? | bool | 同組單選按鈕自動互斥 | autoExclusive: true |
?checked? | bool | 當前選中狀態 | checked: model.isSelected |
?onClicked? | signal | 點擊時觸發 | onClicked: group.update(index) |
?indicator? | Component | 自定義單選按鈕樣式 | indicator: Circle{...} |
?text? | string | 顯示文本標簽 | text: model.option |
代碼示例:
//RadioDelegateproperty string selectedItem: "Item 1" // 默認值需與初始checked項匹配ListView {id: listViewRadiox: 640; y: 0width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: RadioDelegate {text: modelDatawidth: listViewRadio.widthchecked: selectedItem === modelDataonCheckedChanged: {if (checked) {selectedItem = modelData}}}}Button {text: "Selected Item"anchors.bottom: listViewRadio.bottomanchors.horizontalCenter: listViewRadio.horizontalCenteronClicked: console.log("Selected Item:", selectedItem)}
運行結果:
4.SwitchDelegate
屬性/信號/方法 | 類型 | 說明 | 示例 |
---|---|---|---|
?position? | real | 滑塊位置(0.0-1.0) | position: 0.7 |
?checked? | bool | 當前開關狀態 | checked: model.active |
?onToggled? | signal | 狀態變化時觸發 | onToggled: settings.save() |
?indicator? | Component | 自定義滑塊組件 | indicator: Slider{...} |
?visualPosition? | real | 動畫過渡中的可視位置 | visualPosition: 0.5 |
代碼示例:
//SwitchDelegateListView {id: listViewSwitchx: 0; y: 320width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: SwitchDelegate {text: modelDatawidth: listViewSwitch.width}}
運行結果:
?5.SwipeDelegate
屬性/信號/方法 | 類型 | 說明 | 示例 |
---|---|---|---|
?swipe.left? | Component | 左滑時顯示的組件 | swipe.left: Rectangle{...} |
?swipe.right? | Component | 右滑時顯示的組件 | swipe.right: Image{...} |
onCompleted | signal | 完成滑動操作時觸發 | onCompleted: list.remove(index) |
?swipe.position? | real | 當前滑動進度(-1.0到1.0) | swipe.position: 0.3 |
?behind? | Component | 滑動后顯示的背景組件 | behind: DeleteButton{...} |
代碼示例:
//SwipeDelegateListModel {id: listModelListElement { name: "Item 1" }ListElement { name: "Item 2" }ListElement { name: "Item 3" }ListElement { name: "Item 4" }ListElement { name: "Item 5" }}// 列表視圖ListView {x: 320; y: 320width: 300height: 300model: listModeldelegate: SwipeDelegate {width: parent.widthheight: 60text: nameswipe.left: Rectangle {width: parent.widthheight: parent.heightcolor: "#ff4444"Label {anchors.centerIn: parenttext: "刪除"color: "white"font.bold: true}// 點擊刪除按鈕時移除項目MouseArea {anchors.fill: parentonClicked: listModel.remove(index)}}// 滑動完成時自動恢復位置//swipe.onCompleted: swipe.close()}// 滾動條ScrollIndicator.vertical: ScrollIndicator {}}
運行結果:
關鍵特性說明:
- 所有Delegate均繼承自
AbstractButton
,支持點擊/按壓等基礎交互- 自定義樣式推薦通過覆蓋
background
和contentItem
實現- SwipeDelegate需配合ListView使用才能獲得完整手勢支持
三、完整代碼
代碼:
import QtQuick 2.6
import QtQuick.Window 2.2
import QtQuick.Controls 2.6Window {visible: truewidth: 960height: 640title: qsTr("Hello World")//ItemDelegateListView {id: listViewItemx: 0; y: 0width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: ItemDelegate {text: modelDatawidth: listViewItem.widthicon.source:"qrc:/image/user.png"icon.color: "transparent"//icon.name: "edit-cut"display: AbstractButton.TextBesideIconhighlighted: ListView.isCurrentItemonClicked: {listViewItem.currentIndex = index;console.log("clicked:", modelData)}}}//CheckDelegateproperty var selectedItems: []ListView {id: listViewCheckx: 320; y: 0width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: CheckDelegate {text: modelDatawidth: listViewCheck.widthonCheckedChanged: {if (checked) {selectedItems.push(modelData)} else {selectedItems = selectedItems.filter(item => item !== modelData)}}}}Button {text: "Selected Items"anchors.bottom: listViewCheck.bottomanchors.horizontalCenter: listViewCheck.horizontalCenteronClicked: {console.log("Selected items:", selectedItems)}}//RadioDelegateproperty string selectedItem: "Item 1" // 默認值需與初始checked項匹配ListView {id: listViewRadiox: 640; y: 0width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: RadioDelegate {text: modelDatawidth: listViewRadio.widthchecked: selectedItem === modelDataonCheckedChanged: {if (checked) {selectedItem = modelData}}}}Button {text: "Selected Item"anchors.bottom: listViewRadio.bottomanchors.horizontalCenter: listViewRadio.horizontalCenteronClicked: console.log("Selected Item:", selectedItem)}//SwitchDelegateListView {id: listViewSwitchx: 0; y: 320width: 300height: 300model: ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]delegate: SwitchDelegate {text: modelDatawidth: listViewSwitch.width}}//SwipeDelegateListModel {id: listModelListElement { name: "Item 1" }ListElement { name: "Item 2" }ListElement { name: "Item 3" }ListElement { name: "Item 4" }ListElement { name: "Item 5" }}// 列表視圖ListView {x: 320; y: 320width: 300height: 300model: listModeldelegate: SwipeDelegate {width: parent.widthheight: 60text: nameswipe.left: Rectangle {width: parent.widthheight: parent.heightcolor: "#ff4444"Label {anchors.centerIn: parenttext: "刪除"color: "white"font.bold: true}// 點擊刪除按鈕時移除項目MouseArea {anchors.fill: parentonClicked: listModel.remove(index)}}// 滑動完成時自動恢復位置//swipe.onCompleted: swipe.close()}// 滾動條ScrollIndicator.vertical: ScrollIndicator {}}
}
運行結果: