Automatically passing focus around a grid



  • I'm building a UI that will be controlled by touch, mouse, keyboard, and gamepad.

    Many screens have grids of buttons. I want to be able to use the dpad to move focus between items, and then use the Ⓐ button to invoke the button.

    1. Is there any mechanism for automatically passing focus between items in a focus group based on direction? For example, I'd love it if FocusGroup had methods like moveFocusLeft(), moveFocusRight(), moveFocusUp(), moveFocusDown(). Do such methods exist anywhere, such that I could map dpad presses?
      • My current solution is to create state machines which each screen that pass focus around. This works, but is cumbersome to create and maintain.
    2. Is there any mechanism to register the Ⓐ button to trigger the focused button? With the keyboard, I can tab to a button and hit space to invoke it, with no special event handling for the spacebar.
      • My current workaround is to explicitly handle the Ⓐ button events and run this code:
        if (root.activeFocusItem.clicked) root.activeFocusItem.clicked();
        This works, but seems fragile.


  • Solution I'm using now:

    1. Use the KeyNavigation attached properties on all buttons in QML to specify where focus should move when the arrow keys are pressed. With that keyboard arrow keys pass focus around. Dpad also seems to workout of the box for this; not sure why.

    2. Use the (undocumented) GamepadKeyNavigation object to cause the A button to act the same as pressing the space key.

    Here's an example of a simple 2x2 grid of buttons where focus gets moved by arrow keys and gamepad, and you can use space or 'A' button to press a button:

    import QtQuick 2.6
    import QtQuick.Window 2.2
    import QtQuick.Controls 1.4
    import QtQuick.Layouts 1.3
    import QtGamepad 1.0
    
    Window {
        width:800; height:480
        visible: true
        title: "Grid Navigation Test"
    
        Gamepad {
            id: gamepad
            deviceId: GamepadManager.connectedGamepads.length > 0 ? GamepadManager.connectedGamepads[0] : -1
        }
        GamepadKeyNavigation {
            gamepad: gamepad
            active: true
            buttonAKey: Qt.Key_Space
        }
    
        GridLayout {
            columns: 2
            Button {
                id:b1; text:"B1"
                focus: true
                KeyNavigation.right: b2
                KeyNavigation.down:  b3
            }
            Button {
                id:b2; text:"B2"
                KeyNavigation.left: b1
                KeyNavigation.down: b3
            }
            Button {
                id:b3; text:"B3"
                KeyNavigation.right: b4
                KeyNavigation.up:    b1
            }
            Button {
                id:b4; text:"B4"
                KeyNavigation.left: b3
                KeyNavigation.up:   b2
            }
        }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.