Getting focus/activeFocus status from QML ListView

11,456

Solution 1

I think I found a workaround:

onActiveFocusChanged: { focusChanged(focus) }

This emits the focusChanged signal whenever the active focus changes. Using this, the property bindings (like color: parent.focus ? "red" : "#E6E6E6") work as well.

Full test code:

import QtQuick 1.1

FocusScope {
    width: 960
    height: 540
    id: app
    focus: true

    FocusScope {
        id: leftColumn
        KeyNavigation.right: rightColumn
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.top: parent.top
        width: 250

        onActiveFocusChanged: { focusChanged(focus) }

        Rectangle {
            id: leftBackgroundColor
            anchors.fill: parent
            color: parent.focus ? "red" : "#E6E6E6"

            ListView {
                id: contactsList
                interactive: true
                anchors.fill: parent
                focus: true

                delegate: Text {
                    text: name
                    font.bold: activeFocus
                }
                model: ListModel {
                    ListElement { name: "Simon" }
                    ListElement { name: "Mary" }
                    ListElement { name: "Jack" }
                    ListElement { name: "Frank" }
                }

            }
        }
     }


    FocusScope {
        id: rightColumn
        focus: true
        KeyNavigation.left: leftColumn

        anchors.left: leftColumn.right
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.top: parent.top

        onActiveFocusChanged: { focusChanged(focus) }

        Rectangle {
            id: rightBackgroundColor
            anchors.fill: parent
            focus: true
            color: activeFocus ? "red" : "#b3b3b3"            
        }
    }
}

Solution 2

I know that this is an old question, but I think it still deserves a proper explanation, as the same model of focus is still used in QtQuick 2.

How can I check whether the ListView or one of it's children has focus?

The central problem here is that you appear to be a little confused about the meanings of the two focus properties (and that's understandable, it's a bit non-obvious).

To see if a FocusScope (or any of its children) has focus right now, you want to check the Item::activeFocus property on it. This means "either I, or one of my children has focus right now", and it's recursively cleared from a FocusScope when focus is moved to another FocusScope.

On the other hand, Item::focus is a request for focus, not information about the current state, so you should not be binding other values on it (e.g. color: foo.focus ? "black" : "red") to it, unless you want to check whether or not the item is capable of gaining focus at some point in the future, not whether it has focus right now.

That explains why you can have something with Item::focus true, while it doesn't actually have focus -- it's not that the signal is missing, it's that you were misusing the property to mean something it isn't.

So, you want something like this:

Rectangle {
        id: leftBackgroundColor
        anchors.fill: parent
        color: leftColumn.activeFocus ? "red" : "#E6E6E6"
}

...

Rectangle {
    id: rightBackgroundColor
    anchors.fill: parent
    focus: true
    color: rightColumn.activeFocus ? "red" : "#b3b3b3"
}
Share:
11,456
Simon Warta
Author by

Simon Warta

Updated on June 04, 2022

Comments

  • Simon Warta
    Simon Warta almost 2 years

    I've a two column layout with a ListView in the left column. With the Left/Right Keys I can change focus between the two parts of the app.

    The active focus of the left column is delegated to the ListView and from there straight to one of it's rows.

    How can I check whether the ListView or one of it's children has focus?

    import QtQuick 1.1
    
    FocusScope {
        width: 960
        height: 540
        id: app
        focus: true
    
        FocusScope {
            id: leftColumn
            KeyNavigation.right: rightColumn
            anchors.bottom: parent.bottom
            anchors.left: parent.left
            anchors.top: parent.top
            width: 250
            focus: true
    
            Rectangle {
                id: leftBackgroundColor
                anchors.fill: parent
                color: contactsList.activeFocus ? "red" : "#E6E6E6"
    
                ListView {
                    id: contactsList
                    interactive: true
                    anchors.fill: parent
                    focus: true
    
                    delegate: Text {
                        text: name
                        font.bold: activeFocus
                    }
                    model: ListModel {
                        ListElement { name: "Simon" }
                        ListElement { name: "Mary" }
                        ListElement { name: "Jack" }
                        ListElement { name: "Frank" }
                    }
    
                }
            }
         }
    
    
        FocusScope {
            id: rightColumn
            KeyNavigation.left: leftColumn
    
            anchors.left: leftColumn.right
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            anchors.top: parent.top
            onFocusChanged: console.log("Right focus changed: " + focus + "/" + activeFocus)
    
            Rectangle {
                id: rightBackgroundColor
                anchors.fill: parent
                focus: true
                color: activeFocus ? "red" : "#b3b3b3"            
            }
        }
    }