QML ListView 多选

4
我该如何在QML ListView中选择几个元素并将它们的索引发送到C++代码?
4个回答

5

做以下操作:如果单击一个元素,则设置其属性为已选(或者你想怎么称呼它),并在代理中设置如果选择为true,则应以不同的格式进行格式化。此外,将其添加到某个列表中以便于处理。


根据文档:“委托将根据需要实例化,并且可以随时销毁。它们的父项是ListView的contentItem,而不是视图本身。状态永远不应该存储在委托中。”请确保使用数据模型或其他外部源来存储“selected”属性,而不是委托上的属性。 - Phrogz
@Phrogz 我已经看过那份文档很多次了。如果状态只对每个委托本身有影响,那怎么办呢?如果外部源不需要知道委托内部的状态,我认为这没有问题。你觉得呢? - WJR
@WJR 稍微有点过时了,但由于您的问题没有得到答复:问题在于将选定状态存储在委托中,该委托可能会在视图消失时被销毁,从而导致丢失选定状态。状态需要存储在模型中,然后委托可以以这种方式使用(并修改)它。 - Mitch

3

我很确定无法使QML ListView支持多选。Qt Declarative专注于触摸屏使用,纯触摸界面下没有有意义的多选方式。


1
当然,您可以自由实现一个委托,提供一种机制来自由选择和取消选择单个项目,但是您需要自己实现所有必需的概念。 - teukkam
你对多选 Google 相册的感觉如何?(虽然这已经是6年后的事了,但仍然有意义。) - Kyle Strand
1
你是指移动应用程序,在其中通过长按照片进入(多)选择模式吗?是的,这绝对是在触摸界面中实现多选的一种非常有意义的方式。显然,8年前我完全不知道自己在说什么。自那以后,我基本上已经停止使用Qt,所以我不知道在Qt Quick中今天的情况如何。 - teukkam

2

我曾经遇到了同样的问题,我发现最好的实现方法是在列表视图中创建一个新角色。假设它是“firstname”和“selected”。你需要同时使用onCurrentIndexChanged和onClicked事件,因为如果你滚动,这将改变项目但不是点击。在这两个事件中,把“selected”这个角色改为true,或根据自己的需要进行调整,也许你不需要滚动来选择,因此只使用onClicked事件即可。当单击时,你可以将“selected”这个角色改为true。

onCurrentIndexChanged:
{
mListModel.append({"firstName": newEntry,"selected":true})
}

并且。
onClicked:
{
mListModel.append({"firstName": newEntry,"selected":true})
}

然后您可以在委托中使用高亮,这将根据所选状态更改颜色。

这里是一个完整的代码,已经测试过可用:

//copyright: Dr. Sherif Omran
//licence: LPGL (not for commercial use)

import QtQuick 2.12
import QtQuick.Layouts 1.12

Item {
    property string addnewitem:""
    property int removeitemindex: -1
    property string appenditemstring: ""
    property int appenditemindx:-1
    property int fontpoint: 20
    property int radiuspoint: 14
    property int spacingvalue: 0
    property string delegate_color:"beige"
    property string delegate_border_color:"yellowgreen"
    property string highlight_color:"deeppink"
    signal selectedvalueSignal (string iTemstring, string stateval)
    property string sv: ""
    property int indexcopy:0
    id:lstmodelitem
    width: parent.width
    height: parent.height



    ListModel {
        id : mListModel

        //        ListElement {
        //            firstName : "John"
        //        }


    }
    ColumnLayout {
        anchors.fill: parent
        ListView{
            id : mListViewId
            model:mListModel
            delegate :delegateId
            Layout.fillWidth : true
            Layout.fillHeight: true
            clip: true


            snapMode: ListView.SnapToItem //this stops the view at the boundary
            spacing: spacingvalue

            highlight: Rectangle
            {
                id: highlightid
                width: parent.width
                color: mListModel.selected==="true"?"blue":highlight_color
                border.color: "beige"
                z:3
                opacity: 0.2

            }
            highlightRangeMode: ListView.StrictlyEnforceRange
            highlightFollowsCurrentItem:true
            onCurrentIndexChanged:
            {
                console.log("olistdynamic Indexchanged" + currentIndex)
                mListViewId.currentIndex=currentIndex
                lstmodelitem.selectedvalueSignal(currentIndex, mListModel.selected)
                indexcopy=currentIndex

            }


        }
    }

    function getindex()
    {
        console.log("current index = " + indexcopy)
        return mListViewId.currentIndex
    }

    function setindex(index)
    {
        //console.log("olistdynamic set index"+index)
        mListViewId.currentIndex=index
    }

    function add2Item(newEntry,statev){
        console.log("added item with value = " + newEntry + "state " + statev)
        mListModel.append({"firstName": newEntry,"selected":statev})
    }


    function deleteItem(index){
        mListModel.remove(index,1)
    }

    function appendIdem(index,valueEntry,newselectedsate)
    {
        console.log("append item")
        mListModel.set(index,{"firstName": valueEntry,"selected":newselectedsate})
    }

    Component {
        id : delegateId
        Rectangle {
            id : rectangleId
            width : parent.width  // Remember to specify these sizes or you'll have problems
            height: textId.implicitHeight*1.2
            color: selected==="true"?"blue":delegate_color
            border.color: delegate_border_color
            radius: radiuspoint

            Text {
                id : textId
                anchors.centerIn: parent
                text : firstName
                font.pointSize: fontpoint
            }


            MouseArea {
                anchors.fill: parent
                onClicked: {
                    lstmodelitem.selectedvalueSignal(mListModel.firstName,mListModel.selected)
                    mListViewId.currentIndex=index
                    console.log("current index = " + index)
                    indexcopy=index
                    appendIdem(index,firstName,"true")

                }

                onClipChanged:
                {
                    //console.log("a")
                }





            }

        }
    }


    //if the item has been changed from null to text
    onAddnewitemChanged: {
        console.log("added item" + addnewitem)
        add2Item(addnewitem)
    }
    //remove item with index
    onRemoveitemindexChanged: {
        console.log("remove item")
        deleteItem(removeitemindex)
    }

    //to change the item, change the index first then the string
    onAppenditemstringChanged: {
        appendIdem(appenditemindx,appenditemstring)
    }


}

1

您可以尝试在奇数次点击时获取ListItem的数据并将其存储到数组中,在偶数次点击时从数组中删除ListItem的数据。这可能是一个简单的解决方案,而不是创建一个类似复选框的项目列表。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接