Lecko
Lecko

Reputation: 1425

QML define focus chain sequence with JavaScript

I want to define custom focus chain in QML in a way, that there is a JavaScript function, that decides, which element gets the focus next. The focus chain is defined by array. The code is the following:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5

Window {
    width: 640
    height: 480    
    visible: true
    title: qsTr("Focus sandbox")
    Grid {
        width: 100; height: 100
        columns: 2
        property variant ids: [topLeft,topRight,bottomLeft,bottomRight]
        property variant currentId: 0
        function testFocusDispatcher()
        {
            console.log("Current id: "+currentId)
            if(currentId<3)
            {
                currentId++;
            }
            else
            {
                currentId=0;
            }
            return ids[currentId];
        }

        Rectangle {
            id: topLeft
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            focus: true
            KeyNavigation.tab: parent.testFocusDispatcher();
        }

        Rectangle {
            id: topRight
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            KeyNavigation.tab: parent.testFocusDispatcher();
        }

        Rectangle {
            id: bottomLeft
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            KeyNavigation.tab: parent.testFocusDispatcher();
        }

        Rectangle {
            id: bottomRight
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            KeyNavigation.tab: parent.testFocusDispatcher();
        }
    }
}

I receive a lot of messages like this:

QML KeyNavigation: Binding loop detected for property "tab"

and see from the output, that this function runs more than once for each element. What am I doing wrong?

Upvotes: 0

Views: 383

Answers (1)

luffy
luffy

Reputation: 2388

this is caused because of the binding. Each time "testFocusDispatcher" is executed "currentId" will change which will cause the binding to reevaluate which causes "testFocusDispatcher" to execute etc... you see the problem!

I would instead do something like this:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Focus sandbox")

    Grid {
        id: grid
        columns: 2
        spacing: 2
        property variant ids: [topLeft,topRight,bottomLeft,bottomRight]
        property variant currentId: 0
        Keys.onTabPressed: {
            console.log("Current id: " + grid.currentId)
            if(grid.currentId < 3) {
                grid.currentId++;
            }
            else {
                grid.currentId=0;
            }
        }

        Rectangle {
            id: topLeft
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            focus: grid.ids[grid.currentId] === this
        }

        Rectangle {
            id: topRight
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            focus: grid.ids[grid.currentId] === this
        }

        Rectangle {
            id: bottomLeft
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            focus: grid.ids[grid.currentId] === this
        }

        Rectangle {
            id: bottomRight
            width: 50; height: 50
            color: focus ? "red" : "lightgray"
            focus: grid.ids[grid.currentId] === this
        }
    }
}

Upvotes: 1

Related Questions