如何正确清除Qml ListView选择

How to Correctly Clear Qml ListView Selection

本文关键字:ListView 选择 Qml 清除 何正确      更新时间:2023-10-16

如果我有以下内容:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2    
ApplicationWindow {
    title: qsTr("Hello World")
    width: 800
    height: 700
    visible: true
    property var myArray: [1, 2, 3, 4, 5, 6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: messageDialog.show(qsTr("Open action triggered"));
            }
            MenuItem {
                text: qsTr("E&xit")
                onTriggered: Qt.quit();
            }
        }
    }
    Rectangle {
        id: myButton
        anchors.top: parent.top
        anchors.topMargin: 5
        color: "yellow"
        width: 100
        height: 25
        radius: 3
        anchors.horizontalCenter: parent.horizontalCenter
        Text {
            text: "Clear Selection"
            anchors.fill: parent
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
        }
        MouseArea {
            anchors.fill: parent
            onClicked: {
                myListView.currentIndex = -1
            }
        }
    }
    ListView {
        id: myListView
        width: 300
        anchors.horizontalCenter: parent.horizontalCenter
        anchors.top: myButton.bottom
        anchors.topMargin: 5
        anchors.bottom: parent.bottom
        currentIndex: -1
        //highlightFollowsCurrentItem: false
        highlight: Rectangle {
            color: "pink"
            radius: 3
            width: parent.width - 10
            height: 25
            //y: myListView.currentItem.y
            anchors.horizontalCenter: parent.horizontalCenter
        }
        clip: true
        model: myArray
        delegate: Rectangle {
            width: parent.width - 10
            height: 25
            color: "transparent"
            border.color: "cyan"
            anchors.horizontalCenter: parent.horizontalCenter
            Text {
                text: myArray[index]
                horizontalAlignment: Text.AlignHCenter
                verticalAlignment: Text.AlignVCenter
                anchors.fill: parent
            }
            MouseArea {
                anchors.fill: parent
                onClicked: myListView.currentIndex = index
            }
        }
    }
    MessageDialog {
        id: messageDialog
        title: qsTr("May I have your attention, please?")
        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }
}

单击"清除选择"按钮时,我会收到以下信息:
qrc:/main.qml:67:TypeError:无法读取null的属性
qrc:/main.qml:64:TypeError:无法读取空的属性

如何在不出现错误的情况下清除所选内容?它似乎不会使应用程序崩溃,但我有一个列表视图,它根据另一个列表列表视图的选择而更改,错误发生了好几次,扰乱了Qt Creator中的调试输出。我在Qt 5.4和5.5 中注意到了这一点

ListView的文档中写道:

将为每个列表创建高亮显示组件的实例。生成的零部件实例的几何图形由列表管理,以便与当前项保持一致,除非highlightFollowsCurrentItem属性为false。

因此,您不需要尝试自己管理高亮项目的位置。如果您想定位高亮显示,请创建一个中间父项:

highlight: Item {
    Rectangle {
        color: "pink"
        radius: 3
        width: parent.width - 10
        height: 25
        anchors.horizontalCenter: parent.horizontalCenter
    }
}

至于为什么会发生这种情况,可能是因为高亮显示项已重新排序,使其处于parent属性为null的状态。您可以使用以下代码对此进行测试:

anchors.horizontalCenter: { print(parent); parent.horizontalCenter }

通常的问题是,如果您有一个foo,它应该有bar,那么您将其引用为foo.bar,但是,如果foo没有正确初始化,那么它就不能有bar,因为它还不存在。在您的情况下,parent似乎没有正确初始化,因此它没有widthhorizontalCenter(可能在delegate中)。解决方案是正确初始化要使用其成员的对象,在我们的例子中是parent

我在Qt论坛上问过这个问题(https://forum.qt.io/topic/62328/clearing-a-qml-listview-selection)同样,但stack的响应速度更快。检查父值是否有效:

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
ApplicationWindow {
    title: qsTr("Hello World")
    width: 800
    height: 700
    visible: true
    property int myMargin: 5
    menuBar: MenuBar {
        Menu {
            title: qsTr("&File")
            MenuItem {
                text: qsTr("&Open")
                onTriggered: messageDialog.show(qsTr("Open action triggered"));
            }
            MenuItem {
                text: qsTr("E&xit")
                onTriggered: Qt.quit();
            }
        }
    }
    Rectangle {
        id: myButton
        anchors.top: parent.top
        anchors.topMargin: myMargin
        color: "yellow"
        width: 100
        height: 25
        radius: 3
        anchors.horizontalCenter: parent.horizontalCenter
        Text {
            text: "Clear Selection"
            anchors.fill: parent
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
        }
        MouseArea {
            anchors.fill: parent
            onClicked: {
                myListView.currentIndex = -1
            }
        }
    }
    Rectangle {
        width: 300
        anchors.top: myButton.bottom
        anchors.topMargin: myMargin
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        ListView {
            id: myListView
            anchors.fill: parent
            currentIndex: -1
            spacing: 3
            highlightMoveDuration: 25
            highlight: Rectangle {
                width: parent ? parent.width - 10 : 0
                height: parent ? 25 : 0
                color: "pink"
                radius: 3
                anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
            }
            clip: true
            model: ListModel {
                id: myArray
                Component.onCompleted: {
                    for (var i = 1; i < 46; i++)
                        append({number: i})
                }
            }
            delegate: Rectangle {
                width: parent ? parent.width - 10 : 0
                height: parent ? 25 : 0
                color: "transparent"
                border.color: "cyan"
                anchors.horizontalCenter: parent ? parent.horizontalCenter : undefined
                Text {
                    text: number
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                    anchors.fill: parent
                }
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        myListView.currentIndex = index
                    }
                }
            }
        }
    }
    MessageDialog {
        id: messageDialog
        title: qsTr("May I have your attention, please?")
        function show(caption) {
            messageDialog.text = caption;
            messageDialog.open();
        }
    }
}