5
votes

I am trying to figure out how to properly set focus in my application.

I have a component MyItem.qml, which I want to change its background when any of its children gets focus. I also have a MyDerivedItem.qml that derives from MyItem.qml that also should change the background of the base class if any of its children gets focus.

If I understood the documentation correctly, if a component gets focus the focus property of all its parents in the hierarchy are set to true (or until a FocusScope component is reached).

If this is true, then when I press any of the TextFields in MyItem.qml or MyDerivedItem.qml the myItem.focus property should change to true and the background change its color.

I have tried to make a small example of what I want to do, but it does not behave as I expect.

//main.qml
import QtQuick.Controls 2.0

ApplicationWindow {
    height: 768
    width: 1024
    visible: true

    MyDerivedItem {
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.bottom: parent.bottom
        width: parent.width / 2
    }
    MyDerivedItem {
        anchors.top: parent.top
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        width: parent.width / 2
    }
}

//MyItem.qml
import QtQuick 2.7
import QtQuick.Controls 2.0

Rectangle {
    id: myItem

    default property alias data: column.data

    color: focus ? "red" : "green"

    Column {
        id: column

        TextField {
            placeholderText: "Input Text Here"
        }
    }
}

//MyDerivedItem.qml
import QtQuick 2.7
import QtQuick.Controls 2.0

MyItem {
    id: myDerivedItem

    TextField {
        placeholderText: "Derived Input Text Here"
    }

    TextField {
        placeholderText: "Derived Input Text Here"
    }

    TextField {
        placeholderText: "Derived Input Text Here"
    }

    TextField {
        placeholderText: "Derived Input Text Here"
    }

    //...
}
2

2 Answers

1
votes

This is somewhat doumented here. Accoding to that the propagation is: Qt -> QQuickWindow -> Item-with-focus. There is no traversal of the object tree, but the focusing rather happens directly.

There is one exception to this rule, that is the FocusScope which acts as the focused Item towards the scene or a FocusScope in a higher hirarchy. So basically you can say, in addition to the object-tree, there is a second focus-tree where each node is a FocusScope and all other Items are leaves.
Each FocusScope-Node might have one child that has focus.
Children of an Item in the object-tree might be siblings to their object-parents in the focus-tree.

1
votes

The solution to my problem was a minor change. Adding FocusScope to MyItem.qml as follows:

//MyItem.qml
import QtQuick 2.7
import QtQuick.Controls 2.0

FocusScope {
    id: focusScope

    default property alias data: column.data

    Rectangle {
        id: myItem

        anchors.fill: parent
        color: focusScope.focus ? "red" : "green"

        Column {
            id: column
            anchors.fill: parent

            TextField {
                placeholderText: "Input Text Here"
            }
        }
    }
}