当前位置: 首页 > news >正文

QML视图组件:ListView、GridView、TableView、PathView

列表视图(ListView)

ListView是QML中最常用的视图组件之一,用于显示垂直或水平列表数据,特别适合展示线性排列的大量数据项。

核心概念与特性

ListView基于模型-视图-委托(Model-View-Delegate)模式构建,具有以下特点:

  • 高效渲染​:只渲染当前可见的项目,适合大数据量场景
  • 灵活布局​:支持水平和垂直方向排列
  • 交互丰富​:内置滚动、选择和高亮功能
  • 分组支持​:可按属性对项目进行分组显示

常用属性与方法

核心属性
属性类型默认值说明
modelvariant-数据模型(数字/数组/ListModel/QAbstractItemModel)
delegateComponent-定义每个项目的可视化组件
currentIndexint-1当前选中项的索引
countint-只读,模型中的项目总数
spacingreal0项目之间的间距
布局属性
属性类型默认值说明
orientationenumVertical列表方向(Vertical/Horizontal)
layoutDirectionenumLeftToRight布局方向(LeftToRight/RightToLeft)
headerComponent-列表头部组件
footerComponent-列表尾部组件
交互属性
属性类型默认值说明
highlightComponent-当前选中项的高亮组件
highlightMoveDurationint150高亮移动动画时长(ms)
highlightResizeDurationint0高亮大小调整动画时长(ms)
interactivebooltrue是否允许用户交互
常用方法
方法参数返回值说明示例
positionViewAtIndexindex, modevoid滚动到指定索引位置listView.positionViewAtIndex(5, ListView.Center)
incrementCurrentIndex-void增加当前索引listView.incrementCurrentIndex()
decrementCurrentIndex-void减少当前索引listView.decrementCurrentIndex()
itemAtx, yItem返回指定位置的项let item = listView.itemAt(10, 20)

使用示例

基础列表示例
ListView {width: parent.widthheight: 300model: ListModel {ListElement { name: "Apple"; price: "$2.5" }ListElement { name: "Banana"; price: "$1.2" }ListElement { name: "Orange"; price: "$1.8" }ListElement { name: "Apple"; price: "$2.5" }ListElement { name: "Banana"; price: "$1.2" }ListElement { name: "Orange"; price: "$1.8" }}delegate: ItemDelegate {width: ListView.view.widthtext: model.name + " - " + model.pricehighlighted: ListView.isCurrentItem}highlight: Rectangle {color: "lightblue"radius: 3}}

 

自定义列表项示例
import QtQuick
import QtQuick.ControlsWindow {width: 500height: 680visible: truetitle: qsTr("Hello World")ListModel {id: contactModelListElement {name: "周星星"; number: "138 9527 9527"; image: "images/Chow.png"}ListElement {name: "张三"; number: "138 1234 5678"; image: ""}ListElement {name: "李四"; number: "150 9999 9999"; image: ""}ListElement {name: "王五"; number: "178 2323 1111"; image: ""}ListElement {name: "李老板"; number: "152 6666 6666"; image: ""}ListElement {name: "老王"; number: "189 4567 8910"; image: "images/LaoWang.png"}ListElement {name: "腾讯客服"; number: "0755 1234 657"; image: "images/QQ.png"}ListElement {name: "交警"; number: "122"; image: ""}ListElement {name: "中国移动"; number: "10086"; image: ""}ListElement {name: "小明"; number: "136 8888 8666"; image: ""}ListElement {name: "华天安"; number: "139 9999 9999"; image: ""}ListElement {name: "小卖部"; number: "020 5693 1236"; image: ""}ListElement {name: "Qt Group"; number: "020 9527 9102"; image: "images/qt_logo.png"}ListElement {name: "陈小艳"; number: "010 6666 1523"; image: ""}ListElement {name: "李中达"; number: "136 7777 5555"; image: ""}ListElement {name: "大荣"; number: "0755 6666 2222"; image: ""}ListElement {name: "王子文"; number: "155 5555 5555"; image: ""}ListElement {name: "李二柱"; number: "136 9999 0000"; image: ""}}ListView {id: listViewwidth: parent.widthheight: 620model: contactModelspacing: 3snapMode: ListView.SnapOneItemcurrentIndex: 4function firstVisibleItemIndex() {var firstVisibleY = contentY;var index = Math.floor(firstVisibleY / 50);// 如果index是负数或者超过了模型大小,需要进行调整index = Math.max(0, Math.min(index, model.count - 1));return index;}MouseArea {anchors.fill: parentonClicked: {var delegateHeight = 50var spacing = 3var offsetY = mouse.y +listView.firstVisibleItemIndex() * delegateHeight +listView.firstVisibleItemIndex() * spacinglistView.currentIndex = listView.indexAt(mouse.x, offsetY)console.log("visibleFistIndex: " + listView.firstVisibleItemIndex())}}delegate: Item {id: itemDelegatewidth: parent.widthheight: 50Rectangle {id: contactRectanchors.fill: parentcolor: itemDelegate.ListView.isCurrentItem ? "#A0FFA0" : "#F0F0F0"radius: 16Row {width: parent.widthheight: parent.heightImage {id: contactImagewidth: 40height: 40anchors.verticalCenter: parent.verticalCentersource: (image == "") ? "./images/contact.png" : imagefillMode: Image.PreserveAspectFit}Label {id: nameLabelanchors.left: contactImage.rightanchors.leftMargin: 10anchors.verticalCenter: parent.verticalCenterwidth: 200height: 40font.pixelSize: 32verticalAlignment: Text.AlignVCentercolor: "black"text: name}Label {id: numberLabelanchors.left: nameLabel.rightanchors.verticalCenter: parent.verticalCenterwidth: 400height: 40verticalAlignment: Text.AlignVCenterfont.pixelSize: 32color: "black"text: number}}}}}Button {id: decAllContactwidth: parent.width / 2height: 40anchors.left: parent.leftanchors.bottom: parent.bottomtext: "▼"font.pixelSize: 32font.bold: trueonClicked: {var index = listView.currentIndexindex++if(index >= listView.count){listView.currentIndex = listView.count - 1listView.positionViewAtIndex(listView.count - 1, ListView.Visible)}else{listView.currentIndex = indexlistView.positionViewAtIndex(index, ListView.Visible)}}}Button {id: incContactwidth: parent.width / 2height: 40anchors.right: parent.rightanchors.bottom: parent.bottomtext: "▲"font.pixelSize: 32font.bold: trueonClicked: {var index = listView.currentIndexindex--if(index <= 0){listView.currentIndex = 0listView.positionViewAtIndex(0, ListView.Visible)}else{listView.currentIndex = indexlistView.positionViewAtIndex(index, ListView.Visible)}}}
}

 

栅格视图(GridView)

GridView以二维网格形式排列项目,是构建图库、图标视图等场景的理想选择。

核心概念与特性

GridView具有以下特点:

  • 网格布局​:项目按行和列排列,形成整齐的网格
  • 动态加载​:只渲染可见区域的项目,性能高效
  • 灵活尺寸​:可自定义单元格大小和间距
  • 动画支持​:内置添加/删除项目的动画效果

常用属性与方法

核心属性
属性类型默认值说明
modelvariant-数据模型(数字/数组/ListModel等)
delegateComponent-定义每个单元格的显示组件
cellWidthreal-每个单元格的宽度
cellHeightreal-每个单元格的高度
flowenumLeftToRight项目排列方向(LeftToRight/TopToBottom)
布局属性
属性类型默认值说明
rowsint-显式设置行数(优先于cellHeight)
columnsint-显式设置列数(优先于cellWidth)
layoutDirectionenumLeftToRight布局方向(LeftToRight/RightToLeft)
verticalLayoutDirectionenumTopToBottom垂直布局方向(TopToBottom/BottomToTop)
交互属性
属性类型默认值说明
highlightComponent-当前选中项的高亮组件
highlightFollowsCurrentItembooltrue高亮是否跟随当前项
highlightMoveDurationint150高亮移动动画时长(ms)
interactivebooltrue是否允许用户交互
常用方法
方法参数返回值说明示例
positionViewAtIndexindex, modevoid滚动到指定索引位置gridView.positionViewAtIndex(5, GridView.Beginning)
forceLayout-void强制重新布局网格gridView.forceLayout()
moveCurrentIndexUp-void向上移动当前索引gridView.moveCurrentIndexUp()
moveCurrentIndexDown-void向下移动当前索引gridView.moveCurrentIndexDown()

使用示例

基础网格示例
import QtQuick 2.15
import QtQuick.Controls 2.15GridView {id :gridViewwidth: 300; height: 300cellWidth: 100; cellHeight: 100model: ListModel {ListElement { color: "red" }ListElement { color: "green" }ListElement { color: "blue" }ListElement { color: "yellow" }}delegate: Rectangle {width: GridView.view.cellWidth - 5height: GridView.view.cellHeight - 5color: model.colorborder.width: GridView.isCurrentItem ? 2 : 0border.color: "black"MouseArea {anchors.fill: parentonClicked: gridView.currentIndex = index // 点击时更新当前选中索引}}}

动态增删带动画示例
GridView {id: gridViewanchors.fill: parentcellWidth: 80; cellHeight: 80model: ListModel {id: gridModelListElement { index: 0 }ListElement { index: 1 }}delegate: Rectangle {id: wrapperwidth: GridView.view.cellWidth - 10height: GridView.view.cellHeight - 10color: "lightblue"Text {text: indexanchors.centerIn: parent}// 添加动画GridView.onAdd: SequentialAnimation {PropertyAction { target: wrapper; property: "scale"; value: 0 }NumberAnimation { target: wrapper; property: "scale"; to: 1; duration: 200 }}// 删除动画GridView.onRemove: SequentialAnimation {PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: true }NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 200 }PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }}MouseArea {anchors.fill: parentonClicked: gridModel.remove(index)}}}Button {anchors.bottom: parent.bottomtext: "Add Item"onClicked: gridModel.append({"index": gridModel.count})}

图片网格示例
ListModel {id: listModelListElement {name: "Mike"; portrait: "Mike.png"}ListElement {name: "Brown"; portrait: "portrait.png"}ListElement {name: "Jim"; portrait: "portrait.png"}ListElement {name: "Chow"; portrait: "Chow.png"}ListElement {name: "John"; portrait: "portrait.png"}ListElement {name: "Tom"; portrait: "portrait.png"}}Component {id: gridDelegateItem {width: gridView.cellWidthheight: gridView.cellHeightColumn {anchors.centerIn: parentImage {source: portraitwidth: gridView.cellWidth / 2height: gridView.cellHeight / 2anchors.horizontalCenter: parent.horizontalCenterfillMode: Image.PreserveAspectFit}Label {text: nameanchors.horizontalCenter: parent.horizontalCenter}}MouseArea {anchors.fill: parentonClicked: gridView.currentIndex = index // 点击时更新当前选中索引}}}GridView {id: gridViewanchors.fill: parentcellWidth: width / 2cellHeight: height / 2model: listModeldelegate: gridDelegatefocus: truehighlight: Rectangle {color: "lightgreen"radius: gridView.cellHeight / 8}}

表格视图(TableView)

TableView专门用于显示表格数据,支持多列、表头、排序等功能,适合展示结构化数据。

核心概念与特性

TableView的主要特点包括:

  • 多列支持​:每列可独立定义宽度、标题和显示方式
  • 表头支持​:内置可自定义的表头显示
  • 灵活模型​:支持ListModel、TableModel等多种数据模型
  • 性能优化​:只渲染可见单元格,适合大数据量

常用属性与方法

核心属性
属性类型默认值说明
modelvariant-数据模型(ListModel/TableModel等)
TableViewColumnComponent-定义表格列(role/title/width等)
rowDelegateComponent-定义行的外观
itemDelegateComponent-定义单元格的外观
headerDelegateComponent-定义表头的外观
布局属性
属性类型默认值说明
columnWidthProviderfunction-动态计算列宽的函数
rowHeightProviderfunction-动态计算行高的函数
resizableColumnsboolfalse是否允许调整列宽
resizableRowsboolfalse是否允许调整行高
交互属性
属性类型默认值说明
selectionModeenumNoSelection选择模式(NoSelection/SingleSelection/ExtendedSelection等)
currentRowint-1当前选中行
currentColumnint-1当前选中列
sortIndicatorVisibleboolfalse是否显示排序指示器

使用示例

完整表格示例
import QtQuick
import QtQuick.Controls
import Qt.labs.qmlmodelsWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")// 定义一个表格视图组件TableView {id: tableView  // 组件IDanchors.fill: parent  // 填充父组件columnSpacing: 1  // 列间距为1像素rowSpacing: 1  // 行间距为1像素clip: true  // 启用裁剪,超出部分不显示selectionModel: ItemSelectionModel {}  // 选择模型delegate: tableDelegate  // 设置单元格的委托组件// 表格的数据模型model: TableModel {// 定义两列TableModelColumn { display: "name" }  // 第一列名为"name"TableModelColumn { display: "color" }  // 第二列名为"color"// 表格数据行rows: [{"name": "cat", "color": "black"},{"name": "dog", "color": "brown"},{"name": "bird", "color": "white"},{"name": "fish", "color": "blue"},{"name": "cattle", "color": "dark"},{"name": "tiger", "color": "yellow"}]}// 定义单元格的委托组件Component {id: tableDelegate// 每个单元格是一个矩形Rectangle {implicitWidth: 100  // 默认宽度implicitHeight: 50  // 默认高度border.width: 2  // 边框宽度// 当前单元格是否被选中required property bool current// 根据选中状态改变背景色color: current ? "skyblue" : "white"// 当单元格被回收时暂停动画TableView.onPooled: rotationAnimation.pause()// 当单元格被重用时恢复动画TableView.onReused: rotationAnimation.resume()// 单元格中的文本标签Label {id: labeltext: display  // 显示单元格内容anchors.centerIn: parent  // 居中显示font.pixelSize: 16  // 字体大小}// 旋转动画效果RotationAnimation {id: rotationAnimationtarget: label  // 动画目标为标签from: 0  // 起始角度to: 360  // 结束角度duration: (Math.random() * 5000) + 2000  // 随机持续时间(2-7秒)loops: Animation.Infinite  // 无限循环// running: true  // 运行状态}}}// 自定义列宽数组 宽度和高度200*100property var columnWidths: [200, 100]// 列宽提供函数columnWidthProvider: function(column) {return columnWidths[column]}// 定时器,2秒后触发Timer {running: true  // 自动运行interval: 2000  // 间隔2秒onTriggered: {// 修改第二列的宽度为200tableView.columnWidths[1] = 200// 强制重新布局tableView.forceLayout()}}}
}

 

路径视图(PathView)

PathView允许项目沿自定义路径排列和移动,用于创建轮播图、弧形菜单等非线性布局。

核心概念与特性

PathView的主要特点包括:

  • 自定义路径​:支持直线、曲线、闭合路径等多种路径类型
  • 动态效果​:项目可沿路径平滑移动,支持3D变换效果
  • 视觉控制​:可控制项目在路径不同位置的视觉属性(大小、透明度等)
  • 交互灵活​:支持拖动、自动轮播等交互方式

常用属性与方法

核心属性
属性类型默认值说明
modelvariant-数据模型(数字/ListModel/JS数组)
delegateComponent-定义每个项目的显示组件
pathPath-定义项目移动路径(必需)
currentIndexint0当前选中项的索引
offsetreal0路径上的偏移量(0.0-1.0)
pathItemCountint-同时可见的项目数量
路径属性
属性类型默认值说明
startXreal-路径起始点X坐标
startYreal-路径起始点Y坐标
PathLine--直线路径段
PathQuad--二次贝塞尔曲线
PathCubic--三次贝塞尔曲线
PathAttribute--路径属性(如缩放/透明度)
交互属性
属性类型默认值说明
interactivebooltrue是否允许用户拖动
snapModeenumNoSnap吸附模式(NoSnap/SnapToItem)
flickDecelerationreal100拖动减速系数(越大减速越快)
preferredHighlightBeginreal0高亮起始位置(0.0-1.0)
preferredHighlightEndreal0高亮结束位置(0.0-1.0)
常用方法
方法参数返回值说明示例
positionViewAtIndexindex, modevoid定位视图到指定索引pathView.positionViewAtIndex(3, PathView.Center)
incrementCurrentIndex-void增加当前索引pathView.incrementCurrentIndex()
decrementCurrentIndex-void减少当前索引pathView.decrementCurrentIndex()

使用示例

基础路径视图示例
PathView {width: 400; height: 400model: ListModel {ListElement { name: "Item 1"; color: "red" }ListElement { name: "Item 2"; color: "green" }ListElement { name: "Item 3"; color: "blue" }ListElement { name: "Item 4"; color: "lightgreen"}ListElement { name: "Item 5"; color: "lightblue"}}path: Path {startX: 50; startY: 200PathQuad { x: 200; y: 50; controlX: 125; controlY: 25 }PathQuad { x: 350; y: 200; controlX: 275; controlY: 25 }}delegate: Rectangle {width: 50; height: 50color: model.coloropacity: PathView.isCurrentItem ? 1 : 0.5Text {text: model.nameanchors.centerIn: parent}}}

 

图片按钮轮转示例
import QtQuick
import QtQuick.ControlsWindow {width: 640height: 480visible: truetitle: qsTr("Hello World")// 1. 数据模型:定义9个应用项,每个包含名称(name)和图标路径(icon)属性ListModel {id: appModelListElement { name: "Music"; icon: "images/AudioPlayer_48.png" }ListElement { name: "Movies"; icon: "images/VideoPlayer_48.png" }ListElement { name: "Camera"; icon: "images/Camera_48.png" }ListElement { name: "Pencil"; icon: "images/Pencil_48.png" }ListElement { name: "Calendar"; icon: "images/DateBook_48.png" }ListElement { name: "Message"; icon: "images/EMail_48.png" }ListElement { name: "Search"; icon: "images/Search_48.png" }ListElement { name: "TodoList"; icon: "images/TodoList_48.png" }ListElement { name: "Contacts"; icon: "images/AddressBook_48.png" }}// 2. 委托组件:定义每个应用项的视觉和行为Component {id: appDelegateItem {width: 100height: 100scale: PathView.iconScale  // 绑定路径属性中的动态缩放值// 图标显示(居中,距顶部20像素,开启抗锯齿)Image {id: myIconsource: icon  // 绑定模型中的图标路径y: 20smooth: trueanchors.horizontalCenter: parent.horizontalCenter}// 名称标签(位于图标下方,居中显示)Label {text: namesmooth: trueanchors.top: myIcon.bottomanchors.horizontalCenter: parent.horizontalCenter}// 点击交互:切换当前选中项MouseArea {anchors.fill: parentonClicked: pathView.currentIndex = index  // 通过修改currentIndex实现选中}}}// 3. 高亮组件:定义当前选中项的样式(圆形蓝色背景,尺寸略大于普通项)Component {id: appHighlightRectangle {width: 120height: 120radius: height / 2  // 圆形效果color: "lightskyblue"}}// 4. 路径视图核心组件:沿自定义路径布局项目PathView {id: pathViewanchors.fill: parent  // 填充父容器highlight: appHighlight  // 绑定高亮组件preferredHighlightBegin: 0.5  // 高亮区域居中preferredHighlightEnd: 0.5focus: true  // 允许键盘交互model: appModel  // 绑定数据模型delegate: appDelegate  // 绑定委托组件// 5. 路径定义:通过二次贝塞尔曲线(PathQuad)和动态属性(PathAttribute)实现弧形布局path: Path {startX: 10startY: 50// 路径起点设置图标缩放比例为0.3(最小化)PathAttribute { name: "iconScale"; value: 0.3 }// 第一段二次贝塞尔曲线:从左上到中间,控制点决定曲线弧度PathQuad { x: 300; y: 200; controlX: 50; controlY: 200 }// 路径中点设置图标缩放比例为1.5(最大化)PathAttribute { name: "iconScale"; value: 1.5 }// 第二段二次贝塞尔曲线:从中间到右下PathQuad { x: 590; y: 50; controlX: 550; controlY: 200 }// 路径终点恢复图标缩放比例为0.3PathAttribute { name: "iconScale"; value: 0.3 }}// 6. 信号处理:拖动结束时打印当前选中项索引onMovementEnded: {console.log("currentIndex: " + currentIndex)}}
}

总结

QML提供了丰富多样的视图组件,每种组件都有其独特的优势和适用场景:

  1. ListView​:适合线性列表数据展示,支持分组、页眉页脚等高级功能
  2. GridView​:适合二维网格布局,常用于图库、图标视图等场景
  3. TableView​:专为表格数据设计,支持多列、表头和复杂单元格
  4. PathView​:允许项目沿自定义路径排列,适合轮播图、弧形菜单等

掌握这些视图组件的特性和使用方法,能够帮助开发者构建出更加丰富、动态和用户友好的QML界面。在实际开发中,可以根据具体需求选择合适的组件,甚至组合使用多种组件来实现复杂的界面效果。

http://www.dtcms.com/a/301016.html

相关文章:

  • MyBatis Plus 乐观锁与悲观锁
  • 《C++ list 完全指南:list的模拟实现》
  • NodeJs接入腾讯云存储COS
  • MySQL 用户管理
  • 第六章 JavaScript 互操(3)JS调用.NET
  • Django5.1(131)—— 表单 API二(API参考)
  • 电科金仓 KingbaseES 深度解码:技术突破・行业实践・沙龙邀约 -- 融合数据库的变革之力
  • Java面试宝典:MySQL索引
  • 2-4、Dify案例实践—基于工作流构建商城用户评价智能分析系统
  • PyTorch武侠演义 第一卷:初入江湖 第7章:矿洞中的计算禁制
  • 基于mnn架构在本地 c++运行llm与mllm模型
  • 数据结构基本内容(第四篇:队列)
  • 2025.7.27
  • Java面试题及详细答案120道之(061-080)
  • C++算法竞赛篇(六)一维数组题型讲解
  • 【工具】python汇总发票(含源码)
  • Java排序算法之<希尔排序>
  • 7月27日星期日今日早报简报微语报早读
  • GitHub 趋势日报 (2025年07月25日)
  • Linux 系统网络配置及 IP 地址相关知识汇总
  • STM32 I2C通信完整教程:从协议原理到硬件实现
  • 一文快速了解Docker和命令详解
  • 模拟实现python的sklearn库中的Bunch类以及 load_iris 功能
  • 文件权限标记机制在知识安全共享中的应用实践
  • minio 对象存储
  • java的break能加标签,return可以加标签吗
  • 从一副蓝牙耳机里get倍思的“实用而美”
  • Python 程序设计讲义(23):循环结构——循环控制语句 break 与 continue
  • 背包DP之多重背包
  • 边缘提取算法结合深度学习的肺结节分割预测