QML ListModel
1.简单model
mport QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow { width: 400 height: 500 visible: true // 方法2:在数据项中包含选中状态 ListModel { id: fruitModel2 Component.onCompleted: { append({name: "Apple", cost: 2.45, isSelected: false}) append({name: "Orange", cost: 3.25, isSelected: false}) append({name: "Banana", cost: 1.95, isSelected: false}) append({name: "Grape", cost: 4.50, isSelected: false}) append({name: "Peach", cost: 3.75, isSelected: false}) } function setSelectedIndex(index) { for (var i = 0; i < count; i++) { setProperty(i, "isSelected", i === index) } } function getSelectedIndex() { for (var i = 0; i < count; i++) { if (get(i).isSelected) return i } return -1 } } Column { spacing: 20 anchors.fill: parent anchors.margins: 20 Label { text: "方法2:数据项包含选中状态" font.bold: true } ListView { id: listView2 width: parent.width height: 200 model: fruitModel2 currentIndex: fruitModel2.getSelectedIndex() // 从Model获取选中索引 clip: true delegate: Rectangle { width: listView2.width height: 40 color: isSelected ? "lightgreen" : "white" border.color: "lightgray" Text { text: name + " - $" + cost.toFixed(2) anchors.verticalCenter: parent.verticalCenter x: 10 } MouseArea { anchors.fill: parent onClicked: { fruitModel2.setSelectedIndex(index) } } } } Row { spacing: 10 Button { text: "选中Orange(index=1)" onClicked: fruitModel2.setSelectedIndex(1) } Button { text: "选中Grape(index=3)" onClicked: fruitModel2.setSelectedIndex(3) } Button { text: "清除选中" onClicked: fruitModel2.setSelectedIndex(-1) } } Label { text: "当前选中: " + (fruitModel2.getSelectedIndex() >= 0 ? fruitModel2.get(fruitModel2.getSelectedIndex()).name : "无") } } }

2.给model指定一个属性
import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow { width: 400 height: 500 visible: true // 方法1:使用Model的curIndex属性 ListModel { id: fruitModel1 property int curIndex: -1 // 当前选中索引 ListElement { name: "Apple"; cost: 2.45 } ListElement { name: "Orange"; cost: 3.25 } ListElement { name: "Banana"; cost: 1.95 } ListElement { name: "Grape"; cost: 4.50 } ListElement { name: "Peach"; cost: 3.75 } } Column { spacing: 20 anchors.fill: parent anchors.margins: 20 Label { text: "方法1:使用Model的curIndex属性" font.bold: true } ListView { id: listView1 width: parent.width height: 200 model: fruitModel1 currentIndex: fruitModel1.curIndex // 绑定到Model的curIndex clip: true delegate: Rectangle { width: listView1.width height: 40 color: ListView.isCurrentItem ? "lightblue" : "white" border.color: "lightgray" Text { text: name + " - $" + cost.toFixed(2) anchors.verticalCenter: parent.verticalCenter x: 10 } MouseArea { anchors.fill: parent onClicked: { fruitModel1.curIndex = index // 点击时更新Model的curIndex } } } } Row { spacing: 10 Button { text: "选中Apple(index=0)" onClicked: fruitModel1.curIndex = 0 } Button { text: "选中Banana(index=2)" onClicked: fruitModel1.curIndex = 2 } Button { text: "清除选中" onClicked: fruitModel1.curIndex = -1 } } } }

3.嵌套model代码
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 ApplicationWindow { width: 600 height: 800 visible: true title: "动态嵌套列表示例" // 主数据模型 property var mainData: [ { groupName: "默认组", items: [ { name: "项目1", color: "lightblue" }, { name: "项目2", color: "lightgreen" } ] } ] // 颜色选项 property var colorOptions: ["#FF9999", "#99FF99", "#9999FF", "#FFFF99", "#FF99FF", "#99FFFF"] // 主ListView ListView { id: listView anchors.fill: parent spacing: 20 model: mainData delegate: listDelegate } // ListView的委托组件 Component { id: listDelegate Column { id: listColumn width: listView.width spacing: 10 property int groupIndex: index // 保存当前组的索引 // 组标题行 RowLayout { width: parent.width spacing: 10 Text { text: modelData.groupName font.bold: true font.pixelSize: 16 Layout.fillWidth: true } Button { text: "删除组" onClicked: removeGroup(groupIndex) } } // 内嵌的GridView GridView { id: gridView width: parent.width height: Math.ceil(modelData.items.length / 3) * 100 cellWidth: 100 cellHeight: 100 model: modelData.items delegate: gridDelegate Label { visible: parent.count === 0 anchors.centerIn: parent text: "点击下方按钮添加项目" } } // 添加项目按钮 Button { width: parent.width text: "添加项目到本组" onClicked: addItemToGroup(groupIndex) } } } // GridView的委托组件 Component { id: gridDelegate Rectangle { width: 90 height: 90 color: modelData.color border.color: "black" radius: 5 Column { anchors.centerIn: parent spacing: 5 Text { text: modelData.name font.pixelSize: 12 anchors.horizontalCenter: parent.horizontalCenter } Button { text: "删除" anchors.horizontalCenter: parent.horizontalCenter onClicked: { // 通过parent层级访问外部委托的groupIndex var outerDelegate = parent.parent.parent.parent.parent removeItemFromGroup(outerDelegate.groupIndex, index) } } } } } // 底部控制面板 footer: Row { spacing: 10 padding: 10 Button { text: "添加新组" onClicked: addNewGroup() } Button { text: "清空所有" onClicked: clearAll() } } // === 功能函数 === function addNewGroup() { var groupCount = mainData.length + 1; mainData.push({ groupName: "新组 " + groupCount, items: [] }); mainData = mainData.slice(); } function removeGroup(groupIndex) { mainData.splice(groupIndex, 1); mainData = mainData.slice(); } function addItemToGroup(groupIndex) { var itemCount = mainData[groupIndex].items.length + 1; mainData[groupIndex].items.push({ name: "项目 " + itemCount, color: colorOptions[Math.floor(Math.random() * colorOptions.length)] }); mainData = mainData.slice(); } function removeItemFromGroup(groupIndex, itemIndex) { mainData[groupIndex].items.splice(itemIndex, 1); mainData = mainData.slice(); } function clearAll() { mainData = []; mainData = mainData.slice(); } // // 修改指定ID项的颜色 // function changeItemColor(itemId, newColor) { // if (itemReferences[itemId]) { // itemReferences[itemId].color = newColor // } // } }
2.结果

4.嵌套例子
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 ApplicationWindow { width: 600 height: 400 visible: true title: "ListModel 选择示例" ListModel { id: categoryModel Component.onCompleted: { append({ categoryName: "水果", items: [ {name: "苹果", price: 5.2, isSelected: true}, {name: "香蕉", price: 3.5, isSelected: false}, {name: "橙子", price: 4.8, isSelected: false}, {name: "葡萄", price: 8.0, isSelected: false} ], isSelected: true }); append({ categoryName: "蔬菜", items: [ {name: "胡萝卜", price: 2.3, isSelected: false}, {name: "西红柿", price: 3.8, isSelected: false}, {name: "黄瓜", price: 2.5, isSelected: false} ], isSelected: false }); append({ categoryName: "零食", items: [ {name: "薯片", price: 6.5, isSelected: false}, {name: "巧克力", price: 12.0, isSelected: false}, {name: "饼干", price: 5.5, isSelected: false}, {name: "坚果", price: 15.0, isSelected: false}, {name: "糖果", price: 8.5, isSelected: false} ], isSelected: false }); } } ColumnLayout { anchors.fill: parent spacing: 10 // 显示当前模型状态 ListView { Layout.fillWidth: true Layout.fillHeight: true model: categoryModel delegate: Column { width: parent.width spacing: 5 Text { text: categoryName + (isSelected ? " (选中)" : "") font.bold: true color: isSelected ? "blue" : "black" } Repeater { model: items delegate: Text { text: " - " + name + ": " + price + (isSelected ? " (选中)" : "") color: isSelected ? "green" : "black" } } } } // 按钮区域 RowLayout { Layout.fillWidth: true spacing: 10 TextField { id: id_txt1 width: 50 } Button { text: "选中大分类" onClicked: { // 遍历所有分类 for (var i = 0; i < categoryModel.count; i++) { // 设置第2个分类(索引1)为true,其他为false categoryModel.setProperty(i, "isSelected", i === parseInt(id_txt1.text)); } } } TextField { id: id_txt2 width: 50 } Button { text: "选中小分类" onClicked: { // 获取第3个分类(索引2) var category = categoryModel.get(parseInt(id_txt1.text)); var subModelSize = category.items.count var subModel = category.items for (var j = 0; j < subModelSize; j++) { subModel.setProperty(j, "isSelected", (j === parseInt(id_txt2.text))) } } } } } }

5.例子
import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow { id: root visible: true width: 400 height: 600 title: "使用isSelect属性的ListView" property int sIndex: -1 // 数据模型 - 包含isSelect属性 ListModel { id: listModel ListElement { name: "项目1"; isSelect: true } ListElement { name: "项目2"; isSelect: false } ListElement { name: "项目3"; isSelect: false } ListElement { name: "项目4"; isSelect: false } ListElement { name: "项目5"; isSelect: false } } ListView { id: listView // anchors.fill: parent width: parent.width height: 800 model: listModel spacing: 2 currentIndex: sIndex delegate: Rectangle { id: delegateItem width: listView.width height: 50 color: index === root.sIndex ? "lightblue" : "white" // 选中时变浅蓝色 border.color: "lightgray" border.width: 1 property int selected: isSelect onSelectedChanged: { if(isSelect && -1!==index) { root.sIndex = index console.log("listView.currentIndex", listView.currentIndex) } } Text { text: name anchors.centerIn: parent font.pixelSize: 16 } MouseArea { anchors.fill: parent onClicked: { // 切换当前项的isSelect状态 // listModel.setProperty(index, "isSelect", true) // console.log("点击了:", name, "选中状态:", !isSelect) // console.log(listView.currentIndex) root.sIndex = index } } } } Row { anchors.bottom: parent.bottom TextArea { id: id_txt width: 80 } Button { text: "test" onClicked: { // for(var i=0; i<listModel.count; ++i) { // listModel.setProperty(i, "isSelect", false) // } // listModel.setProperty(parseInt(id_txt.text), "isSelect", true) // console.log(listView.currentIndex) root.sIndex = parseInt(id_txt.text) } } } }
或者
import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow { id: root visible: true width: 400 height: 600 title: "使用isSelect属性的ListView" // 数据模型 - 包含isSelect属性 ListModel { id: listModel ListElement { name: "项目1"; isSelect: true } ListElement { name: "项目2"; isSelect: false } ListElement { name: "项目3"; isSelect: false } ListElement { name: "项目4"; isSelect: false } ListElement { name: "项目5"; isSelect: false } } ListView { id: listView width: parent.width height: 800 model: listModel spacing: 2 delegate: Rectangle { id: delegateItem width: listView.width height: 50 color: index === ListView.view.currentIndex ? "lightblue" : "white" // 选中时变浅蓝色 border.color: "lightgray" border.width: 1 property int selected: isSelect onSelectedChanged: { if(isSelect && -1!==index) { ListView.view.currentIndex = index console.log("listView.currentIndex", listView.currentIndex) } } Text { text: name anchors.centerIn: parent font.pixelSize: 16 } MouseArea { anchors.fill: parent onClicked: { for(var i=0; i<listModel.count; ++i) { listModel.setProperty(i, "isSelect", false) } listModel.setProperty(index, "isSelect", true) console.log(listView.currentIndex) } } } } Row { anchors.bottom: parent.bottom TextArea { id: id_txt width: 80 } Button { id: id_btn text: "test" onClicked: { for(var i=0; i<listModel.count; ++i) { listModel.setProperty(i, "isSelect", false) } listModel.setProperty(parseInt(id_txt.text), "isSelect", true) console.log(listView.currentIndex) } } } }

6.嵌套设置选中
import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 ApplicationWindow { width: 600 height: 400 visible: true title: "ListModel 选择示例" ListModel { id: id_categoryModel Component.onCompleted: { append({ categoryName: "水果", items: [ {name: "苹果", price: 5.2, isSelected: true}, {name: "香蕉", price: 3.5, isSelected: false}, {name: "橙子", price: 4.8, isSelected: false}, {name: "葡萄", price: 8.0, isSelected: false} ], isSelected: true }); append({ categoryName: "蔬菜", items: [ {name: "胡萝卜", price: 2.3, isSelected: false}, {name: "西红柿", price: 3.8, isSelected: false}, {name: "黄瓜", price: 2.5, isSelected: false} ], isSelected: false }); append({ categoryName: "零食", items: [ {name: "薯片", price: 6.5, isSelected: false}, {name: "巧克力", price: 12.0, isSelected: false}, {name: "饼干", price: 5.5, isSelected: false}, {name: "坚果", price: 15.0, isSelected: false}, {name: "糖果", price: 8.5, isSelected: false} ], isSelected: false }); } } function notifyCppCurSheet(name) { console.log("c++ record sheet name", name) } function notifyCppCurDiagram(name) { console.log("c++ record diagram name", name) } ListView { id: id_listview width: parent.width height: 40 model: id_categoryModel orientation: ListView.Horizontal spacing: 3 delegate: Rectangle { width: 100 height: ListView.view.height color: model.isSelected?"lightblue":"gray" Text { anchors.centerIn: parent text: categoryName } MouseArea { anchors.fill: parent onClicked: { for(var i=0; i<id_categoryModel.count; ++i) { id_categoryModel.setProperty(i, "isSelected", false) } model.isSelected = true notifyCppCurSheet(categoryName) } } } } Item { width: parent.width height: parent.height-id_listview.height anchors.top: id_listview.bottom anchors.topMargin: 5 Repeater { model: id_categoryModel Loader { anchors.fill: parent visible: isSelected sourceComponent: GridView { cellWidth: 80 cellHeight: 80 anchors.fill: parent model: items delegate: Rectangle { width: 80 height: 80 Text { anchors.centerIn: parent text: name } color: isSelected?"green":"gray" MouseArea { anchors.fill: parent onClicked: { for(var i=0; i<items.count; ++i) { items.setProperty(i, "isSelected", false) } model.isSelected = true notifyCppCurDiagram(name) } } } } } } } }

长风破浪会有时,直挂云帆济沧海!
可通过下方链接找到博主
https://www.cnblogs.com/judes/p/10875138.html