Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to pass the tab focus to the first visible item in a ListView?



  • Consider the following example:

    main.qml

    import QtQuick 2.15
    import QtQuick.Window 2.15
    import QtQuick.Controls 2.15
    
    ApplicationWindow
    {
        objectName: "awMain"
        title: qsTr("Hello World")
        width: 640
        height: 480
        visible: true
    
        WQTButtonFrame
        {
            id: frHeader
            objectName: "frHeader"
            anchors.left: parent.left
            anchors.top: parent.top
            anchors.right: parent.right
            height: 35
    
            m_LeftText: "Left Top"
            m_MiddleText: "Center Top"
            m_RightText: "Right Top"
            m_BgColor: "#b02010"
        }
    
        ListView
        {
            id: lvListView
            anchors.left: parent.left
            anchors.top: frHeader.bottom
            anchors.right: parent.right
            anchors.bottom: frFooter.top
            currentIndex: -1
            flickableDirection: Flickable.VerticalFlick
            keyNavigationEnabled: true
            highlightFollowsCurrentItem: true
            activeFocusOnTab: false
            clip: true
            cacheBuffer: 300
    
            model: ListModel {}
    
            // item delegate
            delegate: ItemDelegate
            {
                implicitWidth: lvListView.width
                implicitHeight: 25
    
                Rectangle
                {
                    anchors.fill: parent
    
                    Button
                    {
                        text: ">> Click Me! <<"
                        anchors.top: parent.top
                        anchors.bottom: parent.bottom
                        anchors.horizontalCenter: parent.horizontalCenter
                        width: 150
                    }
                }
            }
    
            /**
            * Vertical scrollbar
            */
            ScrollBar.vertical: ScrollBar
            {
                // common properties
                id: sbListView
                parent: lvListView
                visible: true
                minimumSize: 0.1
            }
        }
    
        WQTButtonFrame
        {
            id: frFooter
            objectName: "frFooter"
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            height: 35
    
            m_LeftText: "Left Bottom"
            m_MiddleText: "Center Bottom"
            m_RightText: "Right Bottom"
            m_BgColor: "#1020b0"
        }
    
        onActiveFocusItemChanged:
        {
            // found an item with active focus?
            if (activeFocusItem)
                // get the object name
                console.log(activeFocusItem.objectName);
        }
    
        /**
        * Called after the main window object was created
        */
        Component.onCompleted:
        {
            // fill the grid view
            for (var i = 0; i < 1000; ++i)
                lvListView.model.append({"rowId": i});
        }
    }
    

    WQTButtonFrame.qml

    import QtQuick 2.15
    import QtQuick.Window 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Templates 2.15 as T
    
    T.Frame
    {
        property string m_LeftText
        property string m_MiddleText
        property string m_RightText
        property string m_BgColor: "transparent"
    
        objectName: "frFrame"
    
        Rectangle
        {
            objectName: "rcFrameBg"
            anchors.left: parent.left
            anchors.top: parent.top
            anchors.right: parent.right
            height: 35
            color: m_BgColor
    
            Button
            {
                objectName: "btLeft"
                text: m_LeftText
                anchors.left: parent.left
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                width: 75
            }
    
            Button
            {
                objectName: "btMiddle"
                text: m_MiddleText
                anchors.top: parent.top
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.bottom: parent.bottom
                width: 75
            }
    
            Button
            {
                objectName: "btRight"
                text: m_RightText
                anchors.top: parent.top
                anchors.right: parent.right
                anchors.bottom: parent.bottom
                width: 75
            }
        }
    }
    

    When I navigate with the Tab key through the buttons of the above form, I notice that the focus is always given to the button contained in the first item of the ListView, even if the view is scrolled. In the same way, the focus continue to be passed to buttons located onto invisible items when the focus reach the bottom of the view.

    I need to receive the focus on the button located onto the first VISIBLE item of my ListView, and to pass the focus to the next button on the bottom of the view when the focus reaches the button located on the last VISIBLE item on the bottom of the ListView.

    How can I achieve that?