Qt Quick 与 QML(四)qml中的Delegate系列委托组件
一、概念
在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 {}}
}
运行结果: