QtQuick2 - 当根项的 selecting/clicking outside/inside 时,QML 可重用项焦点发生变化

QtQuick2 - QML reusable item focus changes when selecting/clicking outside/inside of root item

当我单击或选择组件主体外部的另一个项目以调用任何事件(突出显示文本、show/hide 矩形等)时,如何将焦点更改状态实现为可重用的 QML 组件。当项目具有焦点时,我试图在 CheckBox 文本下实现高亮行,并在失去焦点时隐藏它。请帮助我了解更有效的实施方式。这是元素的来源:

BreezeQuickCheckbox.qml

import QtQuick 2.4

Item {
    id: root
    property BreezeQuickPalette palette: BreezeQuickPalette
    property bool checked: false
    property string caption: "Checkbox"
    property int fontSize: 18
    implicitHeight: 48
    implicitWidth: bodyText.width + 48
    Rectangle{
        id: body
        width: 32
        height: 32
        anchors {
            verticalCenter: parent.verticalCenter
            left: parent.left
            leftMargin: 8
            rightMargin: 8
        }
        radius: 2
        border{
            width: 1
            color: palette.iconGrey
        }
        color: "transparent"
    }
    Rectangle{
        id: check
        opacity: 1
        radius: 1
        color: palette.focusColor
        anchors {
            verticalCenter: body.verticalCenter
        }
        anchors.fill: body
        anchors.margins: 4
        transform: Rotation {
            id: checkRotation
            origin.x: check.width/2
            origin.y: check.height/2
            axis {
                x: 1
                y: 1
                z: 0
            }
            angle: 90
            Behavior on angle {
                NumberAnimation {
                    duration: 150
                    easing.type: Easing.InOutQuad
                }
            }
        }
        smooth: true
    }
    Text {
        id: bodyText
        anchors {
            verticalCenter: parent.verticalCenter
            left: body.right
        }
        color: palette.normalText
        text: caption
        anchors.leftMargin: 8
        font.pointSize: fontSize
        verticalAlignment: Text.AlignVCenter
        horizontalAlignment: Text.AlignHCenter
    }
    Rectangle {
        id: highlightLine
        anchors{
            horizontalCenter: bodyText.horizontalCenter
            top: bodyText.bottom
            topMargin: -2
        }
        width: bodyText.width
        height: 2
        color: palette.focusColor
    }
    MouseArea{
        id: bodyArea
        anchors.fill: parent
        hoverEnabled: true
        onEntered: {
            if (checked == false){
                body.border.color = palette.focusColor
            } else if (checked == true){
                body.border.color = palette.lightPlasmaBlue
                check.color = palette.lightPlasmaBlue
            }
        }
        onExited: {
            if (checked == false){
                body.border.color = palette.iconGrey
            }
            if (checked == true){
                body.border.color = palette.focusColor
                check.color = palette.focusColor
            }
        }
        onClicked: {
            if (checked == false){
                checked = true
                body.border.color = palette.lightPlasmaBlue
                checkRotation.angle = 0
            } else if (checked == true){
                checked = false
                body.border.color = palette.focusColor
                checkRotation.angle = 90
            }
        }
    }
    onCheckedChanged: {
        if (checked == true){
            body.border.color = palette.focusColor
            if (bodyArea.containsMouse) {
                check.color = palette.lightPlasmaBlue
                checkRotation.angle = 0
            } else if (!bodyArea.containsMouse){
                check.color = palette.focusColor
                checkRotation.angle = 0
            }
        } else if (checked == false){
            body.border.color = palette.iconGrey
            checkRotation.angle = 90
        }
    }
}

您可以在声明实际行的地方看到这个片段:

    Rectangle {
        id: highlightLine
        anchors{
            horizontalCenter: bodyText.horizontalCenter
            top: bodyText.bottom
            topMargin: -2
        }
        width: bodyText.width
        height: 2
        color: palette.focusColor
    }

这是调色板代码,如果您对它感兴趣 - 它是具有自己调色板的组件的子集:

BreezeQuickPalette.qml

import QtQuick 2.4

QtObject {
    id: palette
    property string theme: "light"


    readonly property color normalText: if (theme == "light"){
                                      charcoalGrey
                                  } else if (theme == "dark"){
                                      cardboardGrey
                                  }
    readonly property color inactiveText: asphalt
    readonly property color activeText: plasmaBlue
    readonly property color linkText: seaBlue
    readonly property color negativeText: iconRed
    readonly property color neutralText: bewareOrange
    readonly property color positiveText: deepGreen
    readonly property color focusColor: plasmaBlue
    readonly property color hoverColor: plasmaBlue
    readonly property color normalBackground: if (theme == "light"){
                                      cardboardGrey
                                  } else if (theme == "dark"){
                                                  charcoalGrey
                                              }

    readonly property color alternateBackground: if (theme == "light"){
                                      steel
                                  } else if (theme == "dark"){
                                                     shadeBlack
                                                 }

    readonly property color paperWhite: "#fcfcfc"
    readonly property color cardboardGrey: "#eff0f1"
    readonly property color iconGrey: "#4d4d4d"
    readonly property color charcoalGrey: "#31363b"
    readonly property color shadeBlack: "#232629"
    readonly property color plasmaBlue: "#3daee9"
    readonly property color iconRed: "#da4453"
    readonly property color dangerRed: "#ed1515"
    readonly property color iconOrange: "#f47750"
    readonly property color bewareOrange: "#f67400"
    readonly property color iconYellow: "#fdbc4b"
    readonly property color sunbeamYellow: "#c9ce3b"
    readonly property color mellowTurquoise: "#1cdc9a"
    readonly property color iconGreen: "#2ecc71"
    readonly property color verdantGreen: "#11d116"
    readonly property color iconBlue: "#1d99f3"
    readonly property color seaBlue: "#2980b9"
    readonly property color skyBlue: "#3498db"
    readonly property color turquoise: "#1abc9c"
    readonly property color deepGreen: "#27ae60"
    readonly property color deepTurquoise: "#16a085"
    readonly property color peach: "#e74c3f"
    readonly property color lightMaroon: "#c0392b"
    readonly property color deepYellow: "#f39c1f"
    readonly property color purple: "#9b59b6"
    readonly property color deepPurple: "#8e44ad"
    readonly property color steelBlue: "#34495e"
    readonly property color charcoal: "#2c3e50"
    readonly property color asphalt: "#7f8c8d"
    readonly property color steel: "#bdc3c7"
    readonly property color grey: "#95a5a6"
    readonly property color lightPlasmaBlue: "#63beed"
}

请帮助我了解如何在单击或选择根项目的 outside/inside 后使此 Rectangle 可见或隐藏。这就是我在可重用 CheckBox 聚焦时试图看到的内容,并在焦点消失并传递到另一个组件甚至在元素外部单击时隐藏下划线。

highlightLine.visible 绑定到 root.activeFocus,这样只有当复选框获得活动焦点时才会突出显示:

Rectangle {
    id: highlightLine
    //...
    visible: root.activeFocus
}

可以通过多种方式设置活动焦点。例如,当用户单击复选框时:

MouseArea{
    id: bodyArea
    onClicked: {
        //...
        root.forceActiveFocus(); //set root's active focus when mouse clicked
    }
}

你可以编写一个简单的程序来验证结果:

Row {
   BreezeQuickCheckbox {}
   BreezeQuickCheckbox {}
   BreezeQuickCheckbox {}
}

有关焦点的详细信息,请查看 Keyboard focus in Qt Quick