如何在Ubuntu QML应用中实现MultipleSelectionListView

我们知道在QML中,实现ListView是非常简单的一件事,但是如果大家想做一个多项选择的ListView,那么我们怎么办呢?我们可以参照在github上的一个MultipleSelectionListView.在它的实现中,它也使用了VisualDataModel QML Component.大家如果想更多了解该API的用法,用参照它的API介绍.


MultipleSelectionListView在Ubuntu的Core Apps里用的比较多,比如在我们的messaging及address book里都有用到,虽然它并不是我们Ubuntu Components里的一个标准的控件.这里我们想特别把它提出来就是希望有开发者能够在有的应用中需要用到时,参考我们这里的实现.


MultipleSelectionVisualModel.qml


import QtQuick 2.2

VisualDataModel {
    id: contactVisualModel

    property alias selectedItems: selectedGroup

    groups: [
        VisualDataGroup {
            id: selectedGroup

            name: "selected"
        }
    ]
}


这里的定义其实就是一个 VisualDataModel.这里我们不累述.这里特别指出是这里有一个定义的groups.它的作用就是在Delegate的model之中定义了一个subset的项.这些项可以被用来filter我们model.这里我们定义了一个叫做" selected"名称的 selectedGroup.


MultipleSelectionListView.qml


ListView {
    id: listView

    /*!
      \qmlproperty model selectedItems

      This property holds the list of selected items
    */
    readonly property alias selectedItems: visualModel.selectedItems
    /*!
      \qmlproperty bool multipleSelection

      This property holds if the selection will accept multiple items or single items
    */
    property bool multipleSelection: true

    /*!
      \qmlproperty model listModel

      This property holds the model providing data for the list.
    */
    property alias listModel: visualModel.model
    /*!
      \qmlproperty Component listDelegate

      The delegate provides a template defining each item instantiated by the view.
    */
    property alias listDelegate: visualModel.delegate

    /*!
      \qmlproperty bool isInSelectionMode

      This property holds a list with the index of selected items
    */
    readonly property bool isInSelectionMode: state === "selection"
    /*!
      This handler is called when the selection mode is finished without be canceled
    */
    signal selectionDone(var items)
    /*!
      This handler is called when the selection mode is canceled
    */
    signal selectionCanceled()

    /*!
      Start the selection mode on the list view.
    */
    function startSelection()
    {
        state = "selection"
    }
    /*!
      Check if the item is selected
      Returns true if the item was marked as selected or false if the item is unselected
    */
    function isSelected(item)
    {
        if (item && item.VisualDataModel) {
            return (item.VisualDataModel.inSelected === true)
        } else {
            return false
        }
    }
    /*!
      Mark the item as selected
      Returns true if the item was marked as selected or false if the item is already selected
    */
    function selectItem(item)
    {
        if (item.VisualDataModel.inSelected) {
            return false
        } else {
            if (!multipleSelection) {
                clearSelection()
            }
            item.VisualDataModel.inSelected = true
            return true
        }
    }
    /*!
      Remove the index from the selected list
    */
    function deselectItem(item)
    {
        var result = false
        if (item.VisualDataModel.inSelected) {
            item.VisualDataModel.inSelected = false
            result = true
        }
        return result
    }
    /*!
      Finish the selection mode with sucess
    */
    function endSelection()
    {
        selectionDone(listView.selectedItems)
        clearSelection()
        state = ""
    }
    /*!
      Cancel the selection
    */
    function cancelSelection()
    {
        selectionCanceled()
        clearSelection()
        state = ""
    }
    /*!
      Remove any selected item from the selection list
    */
    function clearSelection()
    {
        if (selectedItems.count > 0) {
            selectedItems.remove(0, selectedItems.count)
        }
    }
    /*!
      Select all items in the list
    */
    function selectAll()
    {
        if (multipleSelection) {
            visualModel.items.addGroups(0, visualModel.items.count, ["selected"] )
        }
    }

    model: visualModel

    MultipleSelectionVisualModel {
        id: visualModel
    }

    Component.onCompleted: {
        // FIXME: workaround for qtubuntu not returning values depending on the grid unit definition
        // for Flickable.maximumFlickVelocity and Flickable.flickDeceleration
        var scaleFactor = units.gridUnit / 8;
        maximumFlickVelocity = maximumFlickVelocity * scaleFactor;
        flickDeceleration = flickDeceleration * scaleFactor;
    }
}

首先,我们看出它还是一个ListView.在它的里面它使用了一个MultipleSelectionVisualModel.这个Component在我们的上面其实已经介绍过来.它作为一个VisualDataModel,有自己的Model及delegate,所以我们这里的ListView并不提供任何的Model及delegate.为了能够使得MultipleSelectionVisualModel中的数据能够在我们的MultipleSelectionListView外被引用,我们使用了如的alias来实现:

   /*!
      \qmlproperty model listModel

      This property holds the model providing data for the list.
    */
    property alias listModel: visualModel.model
    /*!
      \qmlproperty Component listDelegate

      The delegate provides a template defining each item instantiated by the view.
    */
    property alias listDelegate: visualModel.delegate

同样地,我们也可以在外面访问所有被选中的items:

    /*!
      \qmlproperty model selectedItems

      This property holds the list of selected items
    */
    readonly property alias selectedItems: visualModel.selectedItems


我们的Main.qml主程序设计也较为简单.为了展示数据,我们设计了一个自己的ListModel数据:

Main.qml


        ListModel {
            id: fruitModel

            ListElement {
                name: "apple"
                cost: 2.45
            }
            ListElement {
                name: "orange"
                cost: 3.25
            }
            ListElement {
                name: "banana"
                cost: 1.95
            }
            ListElement {
                name: "grape"
                cost: 4.95
            }
        }


MutipleSelectionListView的使用方法如下:

        MultipleSelectionListView {
            id: view
            clip: true
            anchors.fill: parent
            listModel: fruitModel

            listDelegate: Rectangle {
                id: delegate
                width: view.width
                height: units.gu(10)


                Image {
                    id: fruit
                    height: units.gu(8)
                    width: height
                    source: "images/" + name + ".jpg"
                }

                Text {
                    anchors.left: fruit.right
                    anchors.leftMargin: units.gu(10)
                    anchors.verticalCenter: parent.verticalCenter
                    text: "$" + cost
                }

                Image {
                    anchors.right: parent.right
                    anchors.rightMargin: units.gu(1)
                    anchors.verticalCenter: parent.verticalCenter
                    height: units.gu(4)
                    width: height
                    source: "images/tick.png"
                    visible: view.isSelected(delegate)
                }

                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        if (view.isInSelectionMode) {
                            if ( view.isSelected(delegate))
                                view.deselectItem(delegate)
                            else
                                view.selectItem(delegate)
                        }
                    }
                    onPressAndHold: {
                        console.log("start to select....");
                        view.startSelection()
                    }
                }
            }
            onSelectionDone: console.debug("Selected items:" + view.selectedItems)
        }


在这里,我们给MutipleSelectionListView赋上model及delegate.这是一个非常简单的例子.

运行我们的应用:


 

当我们选上我们需要的项后,点击" Get Selection"按钮,我们可以看到如下的输出:

qml: Selected items are:
qml: count: 3
qml: item: [object Object]
qml: item.model: [object Object]
qml: item.model.name: apple
qml: item.model.index: 0
qml: item: [object Object]
qml: item.model: [object Object]
qml: item.model.name: orange
qml: item.model.index: 1
qml: item: [object Object]
qml: item.model: [object Object]
qml: item.model.name: banana
qml: item.model.index: 2

整个项目的源码在: https://github.com/liu-xiao-guo/multipleselectionlistview

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值