版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Shado_walker/article/details/61202539
在QML中ListView的数据分组与定位显示时,以前使用ListView进行数据分组时,都是在model中加入分组数据(分组的项),然后将model中的数据排好序后全部显示到ListView中,这样做也能达到数据分组的目的,但是数据维护太费力,我们自己好做的事情太多,埋下的隐藏问题也就越多。
这次介绍ListView自身的艺术section属性,可以达到数据分组显示的作用,通过设置如下三个属性:
section.property: "name";
section.criteria: ViewSection.FirstCharacter
section.delegate: sectionHeader
然后实现分组显示的代理sectionHeader,如下:
这里需要注意的是,虽然我们不需要对分组项(上图中的蓝色项)进行管理,但是我们需要对ListModel中要显示数据进行排序管理,不然会出现多个分组,也就是说,section不会自动排序,相同section的model数据必须放在连续的一块,不然的话,不连续的section会分别进行显示,这一点要特别注意(即使这样,也比以前所有的项全都自己管理强的多^_^)。
实现了以上功能后,还想模仿手机的联系人列表,通过右侧的字母进行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分组,中间的红圆形显示当前显示分组的字母,这样,完美实现了数据的分组显示与定位^_^。