【问题标题】:How to pass the key focus to the other item in QML?如何将关键焦点传递给 QML 中的其他项目?
【发布时间】:2018-01-29 06:31:46
【问题描述】:

这是我的 QML 文件中的代码:

ma​​in.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 } }
}

我对这段代码有两个问题:

First.第一个组件已设置为focus: true。然后当按下键时,它将显示文本。但我不清楚为什么单击MyClickableWidget 会使其获得焦点,而另一个小部件会失去焦点?点击事件是否将焦点赋予组件?如果是,哪个部分会获得焦点(scoperectangle)?

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

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

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

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

【问题讨论】:

    标签: qt qml qtquick2


    【解决方案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()
        }
    }
    

    ma​​in.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 才能获取关键事件。要将 item 的 activeFocus 设置为 true,必须满足两个条件

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

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

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

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

    【讨论】:

    • 非常感谢。关于你的代码,我有一个问题。在 MouseArea 中,您已设置父级以获取活动焦点,这里父级是 FocusRect 的实例化?我的意思是,如果您单击第二个矩形,则第二个矩形是父级?此外,我显示的代码来自 QT 文档,正如您所说“如果 FocusScope 获得主动焦点并且有一个焦点设置为 true 的孩子,那么孩子 activeFocus 也为 true”我可以将其理解为设置 [onClicked: { scope. focus = true } ] 在我的代码中,如果我单击第二项,scope.focus 已设置为 true,第一个设置为 false?但为什么第一个为 false?
    • 我的意思是为什么第一个失去主动焦点而第二个获得它。如果首先我点击第一个项目,它的 scope.focus 已设置为 true,然后我点击第二个,此时两个项目的 scope.focus 为 true,对吗?那么为什么第二个有积极的焦点呢?
    • 在 focusScope(或顶级窗口)内,一次只能有一个项目具有焦点。因此,当一个项目获得焦点时,其他所有项目都会自动失去焦点(除非它们在 focusScope 中,在这种情况下,FocusScope 会失去焦点,但其中的项目会保持焦点。此时,它的 activeFocus 为 false)
    • 谢谢。①关于您的代码,当您单击第二项时,矩形(父)具有ActiveFocus。但是,第二个 FocusRect 没有设置焦点:true。为什么第二个 FocusRect 能获得 ActiveFocus? ②另外,在我的代码中,我只是在鼠标事件中将 scope.focus 设置为 true(而不是 forceActiveFocus)。为什么第二个可以获得ActiveFocus?我注释掉鼠标事件,并在范围内插入一行 focus = true 。但是它不起作用,不能将关键焦点传递给其他项目。为什么?
    • ①你提到一个Item要设置activeFocus为true,必须满足两个条件,Item本身的focus属性设置为true。但是,第二个 [FocusRect { color: "palegreen" }] 尚未设置为 true
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-29
    • 1970-01-01
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多