QML中ListView数据的分组与定位显示

    xiaoxiao2021-03-25  102

    在QML中ListView的数据分组与定位显示时,以前使用ListView进行数据分组时,都是在model中加入分组数据(分组的项),然后将model中的数据排好序后全部显示到ListView中,这样做也能达到数据分组的目的,但是数据维护太费力,我们自己好做的事情太多,埋下的隐藏问题也就越多。 这次介绍ListView自身的艺术section属性,可以达到数据分组显示的作用,通过设置如下三个属性: section.property: "name"; section.criteria: ViewSection.FirstCharacter section.delegate: sectionHeader 然后实现分组显示的代理sectionHeader,如下: Component { id:sectionHeader Rectangle { width: parent.width height: 20 color: "steelblue" Label { text: section font.bold: true font.pixelSize: 20 anchors.left: parent.left anchors.leftMargin: 10 } } }设置了分组的显示样式,即可实现通过model中的name字段的首字母进行分组显示。话不多说先上图,其初步效果如下: 这里需要注意的是,虽然我们不需要对分组项(上图中的蓝色项)进行管理,但是我们需要对ListModel中要显示数据进行排序管理,不然会出现多个分组,也就是说,section不会自动排序,相同section的model数据必须放在连续的一块,不然的话,不连续的section会分别进行显示,这一点要特别注意(即使这样,也比以前所有的项全都自己管理强的多^_^)。 实现了以上功能后,还想模仿手机的联系人列表,通过右侧的字母进行ListView的定位,如下先展示其完整代码: import QtQuick 2.5 import QtQuick.Layouts 1.2 import QtQuick.Controls 1.4 import Qt.labs.controls 1.0 import QtQuick.Controls.Styles 1.4 Rectangle { id: root width: 800 height: 600 Component { id:sectionHeader Rectangle { width: parent.width height: 20 color: "steelblue" Label { text: section font.bold: true font.pixelSize: 20 anchors.left: parent.left anchors.leftMargin: 10 } } } Rectangle { width: 200 height: 300 anchors.centerIn: parent color: "grey" ListView { id: list_view anchors.fill: parent clip: true anchors.margins: 5 model: list_model delegate: Rectangle { height: 30 width: parent.width Label { text: name anchors.centerIn: parent color: "green" } } section.property: "name"; section.criteria: ViewSection.FirstCharacter//ViewSection.FullString section.delegate: sectionHeader ScrollBar.vertical: ScrollBar { id: scrollBar onActiveChanged: { active = true; } Component.onCompleted: { scrollBar.handle.color = "red"; scrollBar.active = true; scrollBar.handle.width = 10; } } } Rectangle { id: lab width: 30 height: width color: "red"; radius: width/2 opacity: 0.8 anchors.centerIn: parent Label { id: curLabel font.pixelSize: 26 font.bold: true anchors.centerIn: parent } visible: false } Rectangle { width: 10 height: parent.height-100 anchors.right: parent.right anchors.rightMargin: 10 color: "transparent" anchors.verticalCenter: parent.verticalCenter Column { anchors.centerIn: parent spacing: 3 clip: true Repeater { model: ["a","b","c","d","e","f","g","h","i","j","k"] Label { text: modelData font.pixelSize: 16 horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter MouseArea { anchors.fill: parent hoverEnabled: true onEntered: { console.log("onClicked:", modelData); var idx = getIndexFromLab(modelData); list_view.positionViewAtIndex(idx, ListView.Beginning) lab.visible = true; curLabel.text = modelData } onExited: lab.visible = false; } } } } } } function getIndexFromLab(lab) { var i; for (i=0;i<list_model.count;i++) { if (list_model.get(i).name.substr(0, 1) === lab) { return i; } } return i<=11?i:7; } //测试数据 ListModel{ id:list_model ListElement { name: "aItem1" } ListElement { name: "aItem2" } ListElement { name: "aItem3" } ListElement { name: "bItem4" } ListElement { name: "bItem5" } ListElement { name: "cItem6" } ListElement { name: "cItem7" } ListElement { name: "tItem8" } ListElement { name: "tItem9" } ListElement { name: "tItem10" } ListElement { name: "wItem11" } ListElement { name: "wItem12" } ListElement { name: "wItem13" } ListElement { name: "zItem14" } ListElement { name: "zItem151" } } }以上代码中,不仅实现了model中数据的分组,还通过鼠标滑动到右侧的字母上时自动定位ListView的显示,主要使用了Repeater控件进行分组字母的显示,通过计算鼠标当前在Repeater中的那个字母上,得出ListView中应该展示的索引(这里没有进行详细的计算,只是初步计算,要想精确定位,在这块还得继续优化,请参见下一篇 JS递归调用定位ListView应该定位的项),然后调用ListView的positionViewAtIndex(idx, ListView.Beginning)进行显示的定位,其实现效果如下:

    ​如上图,当鼠标在"c"上时,分组自动定位到C分组,中间的红圆形显示当前显示分组的字母,这样,完美实现了数据的分组显示与定位^_^。

    转载请注明原文地址: https://ju.6miu.com/read-23392.html

    最新回复(0)