如何将关键焦点传递给QML中的其他项?

时间:2018-01-29 06:31:47

标签: qt qml qtquick2

以下是我的QML文件中的代码:

main.qml

Rectangle {
    id: window    
    color: "white"; width: 240; height: 150

    Column {
        anchors.centerIn: parent; spacing: 15

        MyClickableWidget {
            focus: true             //set this MyWidget to receive the focus
            color: "lightblue"
        }
        MyClickableWidget {
            color: "palegreen"
        }
    }    
}

MyClickableWidget.qml

FocusScope {
    id: scope
    //i try to set true instead of the mouse event
    //focus: true
    //FocusScope needs to bind to visual properties of the children
    property alias color: rectangle.color
    x: rectangle.x; y: rectangle.y
    width: rectangle.width; height: rectangle.height

    Rectangle {
        id: rectangle
        anchors.centerIn: parent
        color: "lightsteelblue"; width: 175; height: 25; radius: 10; antialiasing: true
        Text { id: label; anchors.centerIn: parent }
        focus: true
        Keys.onPressed: {
            if (event.key == Qt.Key_A)
                label.text = 'Key A was pressed'
            else if (event.key == Qt.Key_B)
                label.text = 'Key B was pressed'
            else if (event.key == Qt.Key_C)
                label.text = 'Key C was pressed'
        }
    }
    MouseArea { anchors.fill: parent; onClicked: { scope.focus = true } }
}

我对此代码有两个疑问:

首先。第一个组件已设置focus: true。然后按键,它将显示文本。但我不清楚为什么单击MyClickableWidget会使焦点集中而另一个小部件失去焦点? click事件是否将焦点放在组件上?如果是,哪个部分将获得焦点(scoperectangle)?

此外,在我看来,以下显示的行是将scope.focus设置为true。所以,我注释掉这一行,在focus = true中插入一行scope。但是它不起作用,无法将关键焦点传递给其他项目。为什么呢?

// MouseArea { anchors.fill: parent; onClicked: { scope.focus = true } }

结果是一样的。我不知道为什么代码需要这一行。

第二。在焦点范围内,如果孩子拥有focus: true,则会自动设置所有父和根focus: true?如果不在焦点范围内,结果是否相同?

1 个答案:

答案 0 :(得分:1)

为什么首先需要FocusScope?如果你摆脱它,你的代码可以大大简化。

重要的是要知道,在FocusScope内,一次只能有一个项目。应用程序窗口的行为类似于FocusScope。为了简单起见,如果一个项目获得焦点,之前有焦点的项目会自动失去它。

<强> FocusRect.qml

Rectangle {
    width: 175;
    height: 25;
    radius: 10;

    Text { id: label; anchors.centerIn: parent }

    Keys.onPressed: {
        if (event.key == Qt.Key_A)
            label.text = 'Key A was pressed'
        else if (event.key == Qt.Key_B)
            label.text = 'Key B was pressed'
        else if (event.key == Qt.Key_C)
            label.text = 'Key C was pressed'
    }

    MouseArea
    {
        anchors.fill: parent
        onClicked: parent.forceActiveFocus()
    }
}

<强> main.qml

ApplicationWindow {

    width: 960
    height: 540

    Column {
        anchors.centerIn: parent; 
        spacing: 15

        FocusRect {
            focus: true             //set this MyWidget to receive the focus
            color: "lightblue"
        }
        FocusRect {
            color: "palegreen"
        }
    }
}

这里的行为是直截了当的。项必须具有activeFocus才能获取关键事件。对于将activeFocus设置为true的Item,必须满足两个条件

  • 项目本身的焦点属性设置为true
  • 其最近的FocusScope父级具有activeFocus,或者没有focusScope父级,并且应用程序窗口具有活动焦点。

在这个简单的例子中,将MyClickableWidget的焦点设置为true也会将其activeFocus设置为true(无父FocusScope),使其能够获取KeyEvents。

在回答您的第二个问题时,在FocusScope内,将项目的焦点设置为true将不会产生任何副作用。但是,强制它获得activeFocus(通过在其上调用forceActiveFocus())将使其所有FocusScope父项获得activeFocus(并因此将焦点设置为项目的父级层次结构中所有FocusScope的true)

相反,如果FocusScope获得活动焦点并将焦点设置为true的子节点,则子activeFocus也将设置为true。