Search code examples
qtlistviewpyqtqmlpyside

Is there a way to make unselectable a "list item" in ListView?


I am new to Qt. Wondering if there a possibility to make an item "unselectable" in ListView.

I see there are a lot of other things, e.g: collapsing , expanding, etc. ** I have not find any simple example for this problem. **

Can you provide some minimalistic examples to make a specific item in the list unselectable?

I have the following minimalistic example. How can I set list item index 2 to be unselectable?

Window {
   id: mainWindow
    width: 130
    height: 240
    visible: truetitle: qsTr("Hello")

    Rectangle {
        id: bg
        color: "#ffffff"
        anchors.fill: parent
    
        ListModel {
            id: nameModel
            ListElement { name: "Alice" }
            ListElement { name: "Bob" }
            ListElement { name: "Jay" }
            ListElement { name: "Kate" }
        }
        Component {
            id: nameDelegate
            Text {
                text: model.name
                font.pixelSize: 24
            }
        }
        ListView {
            anchors.fill: parent
            model: nameModel
            delegate: nameDelegate
            clip: true
    
            highlight: Rectangle {
                anchors { left: parent.left; right: parent.right }
                //height: parent.height
                color: "lightgrey"
            }
        }
    }
}

Solution

  • I found numerous issues with your code snippet, so I attempted to address them all:

    • I made use of Page and set Page.background instead of declaring an outer Rectangle. This removes a level of indentation
    • I refactored NameComponent.qml to reduce the complexity of your main program
    • I change the delegate from Text to ItemDelegate so that it is clickable, and, it being clickable, I can (1) make the ListView have active focus so that it can receive keyboard events, (2) change the current item in the ListView => I think this achieves your criteria of being able to select a different item
    • I removed unnecessary anchoring from your highlight - your highlight will default anchor to your selected item
    • I set the width of your delegate to listView.width - I also made use of the ListView.view attached property so that your delegate and access properties from the ListView
    • Finally, I added a 20 pixel width vertical ScrollBar
    import QtQuick
    import QtQuick.Controls
    Page {
        background: Rectangle { color: "#ffffff" }
        
        ListModel {
            id: nameModel
            ListElement { name: "Alice" }
            ListElement { name: "Bob" }
            ListElement { name: "Jay" }
            ListElement { name: "Kate" }
        }
    
        ListView {
            anchors.fill: parent
            model: nameModel
            delegate: NameDelegate { }
            clip: true
            highlight: Rectangle {
                color: "lightgrey"
            }
            ScrollBar.vertical: ScrollBar {
                width: 20
                policy: ScrollBar.AlwaysOn
            }
        }
    }
    
    // NameDelegate.qml
    import QtQuick
    import QtQuick.Controls
    ItemDelegate {
        property ListView listView: ListView.view
        width: listView.width - 20
        text: model.name
        font.pixelSize: 24
        onClicked: {
            listView.forceActiveFocus();
            if (listView.currentIndex === index) {
                listView.currentIndex = -1;
            } else {
                listView.currentIndex = index;
            }
        }
    }
    

    You can Try it Online!