Как отключить элемент, имеющий активный фокус в QML, используя привязку свойства? - PullRequest
0 голосов
/ 08 марта 2020

Рассмотрим следующую программу QML, состоящую из двух файлов.

Файл main.qml :

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
    width:   600
    height:  600
    visible: true

    FocusScope {
        property string name: "FocusScope"

        Column {
            MyRectangle {
                id:   rectA
                name: "A"
            }

            MyRectangle {
                name: "B"
            }

            MyRectangle {
                id:   rectC
                name: "C"
            }

            MyRectangle {
                id:   rectD
                name: "D"
            }

            MyRectangle {
                name: "E"
            }
        }
    }

    onActiveFocusItemChanged: {
        console.log("active focus changed to: " + activeFocusItem.name)
    }

    Component.onCompleted: {
        rectA.forceActiveFocus()
    }
}

Где MyRectangle определено в файле MyRectangle.qml :

import QtQuick 2.6

Rectangle {
    property string name

    width:            50
    height:           50
    color:            enabled ? (focus ? "red" : "black") : "lightgrey"
    activeFocusOnTab: true

    function enableWithActiveFocus(enabled)
    {
        if (enabled === this.enabled) {
            return
        }

        if (enabled) {
            this.enabled = true
            return
        }

        if (activeFocusItem === this) {
            nextItemInFocusChain(true).forceActiveFocus()
        }

        this.enabled = false
    }

    Text {
        anchors.centerIn: parent
        color:            "white"
        text:             name
    }

    Keys.onReturnPressed: {
        rectC.enableWithActiveFocus(!rectC.enabled)
    }
}

Эта программа позволяет перемещаться между пятью прямоугольниками с помощью клавиш Tab и BackTab (Shift + Tab). «Навигация» означает «изменить активный фокус» - прямоугольник с активным фокусом выделяется красным. Можно также нажать клавишу Enter, чтобы отключить или включить rectC (третий прямоугольник) - отключено rectC становится серым.

Наиболее интересным является случай, когда кто-то перемещает активный фокус на rectC, а затем делает это отключено. Что должно произойти с активным фокусом в этом случае? Я хочу, чтобы в этом случае активный фокус передавался следующему прямоугольнику в цепочке фокусировки, т.е. rectD. Однако QML работает так, что если мы просто изменим свойство enabled элемента, имеющего активный фокус, на false (вызывая, например, rectC.enabled = false), этот элемент сначала теряет активный фокус, а затем становится отключенным ( в данном примере потерянный активный фокус будет получен группой FocusScope). Когда активный фокус теряется элементом, невозможно знать, какой элемент следующий за этим элементом в цепочке фокусировки. И это проблема!

Вот почему я реализовал функцию enableWithActiveFocus() и использую только ее, чтобы сделать прямоугольник отключенным или включенным. Когда кто-то делает прямоугольник с активным фокусом отключенным с помощью этой функции, функция сначала перемещает активный фокус на элемент, следующий за цепочкой фокусировки, а затем отключает начальный элемент. Без потери активного фокуса!

Мой вопрос: Есть ли возможность каким-либо образом реализовать то же поведение (передача активного фокуса следующему элементу, когда текущий элемент имеет активный фокус и отключен ) с помощью простого связывания свойств QML? Например, я хочу иметь что-то вроде этого:

Файл main.qml :

import ...

Window {
    ...

    FocusScope {
        ...

        Column {
            ...

            MyRectangle {
                id:   rectC
                name: "C"
                enabled: myProperty
            }

            ...
        }
    }

    ...
}

Файл MyRectangle.qml :

import ...

Rectangle {
    ...

    Keys.onReturnPressed: {
        myProperty = !myProperty
    }
}

К сожалению, нельзя реализовать onEnabledChanged обработчик событий для MyRectangle, который позволял бы передавать активный фокус следующему элементу в цепочке фокусировки, когда текущий элемент имеет активный фокус и отключается, потому что когда мы отключаем элемент с активным фокусом, этот обработчик событий вызывается, когда активный фокус уже потерян. Поэтому нельзя знать, какой элемент является следующим для текущего элемента.

Спасибо за любые подсказки!

...