How to pass the key focus to the other item in QML?
这是我的QML文件中的代码:
main.qml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| 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事件是否将焦点集中在组件上? 如果是,哪个部分将获得焦点(scope或rectangle)?
另外,我认为,如下所示的行是将scope.focus设置为true。 因此,我将这一行注释掉,在scope中插入一行focus = true。 但是,它不起作用,无法将重点转移到其他项目。 为什么?
1
| // MouseArea { anchors.fill: parent; onClicked: { scope.focus = true } } |
结果是一样的。 我不知道为什么代码需要这一行。
第二。 在焦点范围内,如果子级具有focus: true,则所有父级和根级都将自动设置为focus: true? 如果不在焦点范围内,结果是否相同?
为什么首先需要FocusScope?如果您将其删除,则可以大大简化您的代码。
要知道的重要一点是,在FocusScope中,一次只能有一个项目具有焦点。应用程序窗口的行为类似于FocusScope本身。为简单起见,如果某个项目获得了焦点,则先前具有焦点的项目会自动失去它。
FocusRect.qml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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,必须满足两个条件
-
项目本身的focus属性设置为true
-
它最接近的FocusScope父级具有activeFocus或没有focusScope父级,并且应用程序窗口具有活动焦点。
在这个简单的示例中,将MyClickableWidget的焦点设置为true还将其activeFocus设置为true(没有父FocusScope),从而使其能够获取KeyEvents。
在FocusScope内回答第二个问题时,将项目的焦点设置为true不会有副作用。但是,强迫它获得activeFocus(通过在其上调用forceActiveFocus())将使其所有FocusScope父级都获得activeFocus(因此,将该项的父级层次结构中的所有FocusScope的focus设置为true)
相反,如果FocusScope获得活动焦点并将子项的焦点设置为true,则子项activeFocus也将设置为true。
-
非常感谢你。关于您的代码,我有一个问题。在MouseArea中,您已将父级设置为获得主动焦点,这里父级是FocusRect的实例化?我的意思是,如果您单击第二个rect,则第二个rect是父对象?另外,我显示的代码来自QT文档,正如您所说的:"如果FocusScope获得了主动焦点,并且将子项的焦点设置为true,则子项activeFocus也为true",我可以理解为设置[onClicked:{范围。在我的代码中,如果我单击第二项,则scope.focus已设置为true,而第一个设置为false?但是为什么第一个为false?
-
我的意思是为什么第一个失去主动关注,第二个获得关注。如果首先我单击第一个项目,则将scope.focus设置为true,然后单击第二个,那时两个项目scope.focus为真,对吗?那么,为什么第二个要积极关注呢?
-
在focusScope(或顶级窗口)中,一次只能有一个项目具有焦点。因此,当一个项目获得焦点时,其他所有项目都会自动失去焦点(除非它们位于focusScope中,否则,FocusScope会失去焦点,但其中的项目会保持焦点。这时,其activeFocus为false)
-
谢谢。①关于您的代码,当您单击第二项时,矩形(父级)具有ActiveFocus。但是,第二个FocusRect不会设置焦点:true。为什么第二个FocusRect可以获取ActiveFocus? ②此外,在我的代码中,我只是在鼠标事件中将scope.focus设置为true(而不是forceActiveFocus)。为什么第二个可以获得ActiveFocus?我注释掉鼠标事件,并在范围中插入一行focus = true。但是它不起作用,不能将关键焦点传递给其他项目。为什么?
-
①您已经提到将activeFocus设置为true的Item,必须满足两个条件,Item本身的focus属性设置为true。但是,第二个[FocusRect {color:" palegreen"}]尚未设置为true
-
forceActiveFocus使Item及其所有父focusScope获得焦点,因此该项目获得activeFocus。对于简单的用例,不涉及FocusScope,等效于set focus = true。
-
我知道,但是在您的代码中,您没有使用focusScope,这就是为什么我无法理解第二个对象[FocusRect {color:" palegreen"}]可以获取activeFocus的原因。另外,在我的代码中,为什么第二个set focus = true可以获取activeFocus(如果使用我可以理解的forceActiveFocus)
-
如果没有focusScope,则将focus设置为true就像调用forceActiveFocus一样,这意味着该项目将获得焦点和活动焦点,而其他所有项目都将失去焦点。
-
请原谅我问你很多问题,非常感谢你。但是我认为你误解了我的问题。为了回答您的问题,我有两个问题。①在显示给我的代码中,您没有使用focusScope。然后,您可以使用鼠标事件来设置Rectangle以获得ActiveFocus。正如您所说的Item具有activeFocus一样,必须满足两个条件,Item本身的focus属性设置为true。我的问题是第二个问题[FocusRect {color:" palegreen"}]尚未将焦点设置为真实。如何获得ActiveFocus
-
②第二个问题是关于我的代码的,我在问题中显示了它。我使用focusScope!为什么第二个set focus = true(mouse event)可以获得activeFocus(如果使用forceActiveFocus我可以理解)
-
让我们再试一次。解答1.在mouseArea onClicked事件中,我在mouseAreas父对象上调用forceActiveFocus。该父对象是FocusRect组件的Root矩形。因此,当我单击鼠标区域时,会在FocusRect上调用forceActiveFocus。顾名思义,forceActiveFocus()会将焦点设置为true,并确保任何现有的父focusScope也将焦点设置为true。在我的示例中,我可以使用onClicked:parent.focus = true,结果相同
-
答案2:在鼠标区域中,将scope设置为focus = true。范围是MyClickableWidget组件的根FocusScope。没有更高的FocusScope组件阻止它在获得焦点时获得activeFocus,因此再次调用forceActiveFocus并将focus设置为true将等同于STRICLTY。
-
对于简单情况,我的建议是:不要为FocusScope烦恼,如果要在某个项目上设置焦点,则可以调用forceActiveFocus(),仅此而已。
-
非常感谢您,我几乎了解您的意思!但是,将焦点转移到其他项目上只是一个小问题!我可以理解为当我使用鼠标单击项目时,我单击的项目可以获取"焦点",然后继续检查焦点参数是否具有ActiveFocus?(如果我单击了项目区域之外的项目) ,没有任何反应)。在那种情况下,如果我使用键事件而不是鼠标事件,就无法将焦点切换到其他项目,对吗?(只需将代码从MouseArea {...}复制到Keys.onPressed:..)
-
按键事件和鼠标事件的工作方式不同。 MouseEvent与焦点无关;如果单击启用的MouseArea,它将收到clickEvent,并会调用onClicked处理函数。而已。另一方面,键事件仅在定义键处理程序的项目具有activeFocus时才起作用(因此一次仅一个项目)。例如,这将阻止您同时输入两个文本字段,这通常是您要避免的事情。