开发者

QML ListView multiselection

How can I select a few elements in th开发者_开发问答e QML ListView and send its indices to C++ code?


Do something like that: if an element is clicked, set its property selected (or however you call it), and set in delegate that if selected is true, then it should be formatted differently. Plus add it to some list, to work with it.


I am pretty sure there is no way to make a QML ListView multi-selectable. Qt Declarative is focused on touch screen use and there is no meaningful way to multiselect in a pure touch UI.


i had the same issue and i found the best way to implement it, is to create a new role to the listview. Lets assume it is firstname and selected. you need to use both onCurrentIndexChanged and onClicked, because if you scroll, this will change the item but it is not a click. In both of them change the role selected into true, or adjust as it suits you, may be you don't need scroll to select and thus use only the onClicked. When clicked you can change the role selected into true

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

and

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

then you may use a highlight in the deligate, this will change the color based on the state of the selected.

Here is a full code that is tested to work

//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)
    }


}


You may try to get the ListItem's data and store it to an array on odd click and remove the ListItem's data from the array on even click. May be a simple workout, instead of creating a list of check box like items.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜