如何在我的自定义 QML 组件中使用状态管理焦点?
How to manage Focus with States in my custom QML component?
我创建了一个可拖动的自定义组件,以便管理各个快速控制组件的几何形状。
该组件有 2 个部分:
- "Manipulator" 是一个可拖动和可调整大小的矩形
- 位于操纵器中心的内部组件
行为描述:
- 无焦点:默认状态,Manipulator不可见
而且你只能看到内部组件
- Focused:当您单击组件(或尝试拖动它)时,您进入
此状态和操纵器变得可见,但您无法访问
内部组件。禁用按 Escape 键或在组件外部单击(进入状态 1)
- Inner Focus: 当你双击组件 The Manipulator
保持可见,您仍然可以调整大小,但内部
组件具有主要焦点(例如 TextEdit 现在可以是
可编辑)。禁止按下 Escape(进入状态 2)或点击组件外(进入状态 1)
Example of the Component when the Manipulator area is visible
此组件的逻辑类似于桌面环境中文件夹的逻辑(调整大小除外)操纵器将是文件夹本身,内部组件是其名称。
这里是我的 post 我的操纵器的简化版本,我相信它会帮助构建一个答案,(我尝试了几个小时的很多变体,这是那些没有功能的尝试之一)
FocusScope{
id: root
width: 175; height: 25;
focus: true
states: [
State {
name: "noFocus"
when: !manipulator.activeFocus && !innerComp.activeFocus
PropertyChanges {
target: innerComp
enabled: false
}
PropertyChanges {
target: manipulator
visible: false
}
},
State {
name: "focused"
when: manipulator.activeFocus
PropertyChanges {
target: innerComp
enabled: false
}
PropertyChanges {
target: manipulator
visible: true
}
},
State {
name: "innerFocus"
when: innerComp.activeFocus
PropertyChanges {
target: innerComp
enabled: true
}
PropertyChanges {
target: manipulator
visible: true
}
}
]
//visual area of manipulation (drag, redimension, etc)
MouseArea{
id: manipulator
anchors.fill: parent
onDoubleClicked: forceActiveFocus(innerComp) //go to state 3 "innerFocus"
drag.target: manipulator
Keys.onEscapePressed: forceActiveFocus(root) //I don´t think this is the correct to loose focus but I don´t know how to do that
Rectangle {
id: background
anchors.fill: parent
color: "lightsteelblue";
}
}
//Inner Component (TextField for example)
InnerComp {
id: innerComp
anchors.fill: parent
Keys.onEscapePressed: forceActiveFocus(manipulator) //return state 2 "focused"
}
}
我终于找到了解决方案,正如 qt 论坛中有人所建议的那样:
Maybe reverse the dependency, i.e. make the focus depend on the state, not the state depend on the focus?
所以我更改了我的代码,现在可以使用了!
我post这里为那些可能对此感兴趣的人提供解决方案(正如我所说,这是真实代码的简化版本):
Item {
id: root
width: 175; height: 25;
states: [
State {
name: "noFocus"
PropertyChanges {
target: innerComp; enabled: false
}
PropertyChanges {
target: background; visible: false
}
PropertyChanges {
target: manipulator; focus: true
}
},
State {
name: "focused"
PropertyChanges {
target: innerComp; enabled: false
}
PropertyChanges {
target: background; visible: true
}
PropertyChanges {
target: manipulator; focus: true
}
},
State {
name: "innerFocus"
PropertyChanges {
target: innerComp; enabled: true
}
PropertyChanges {
target: background; visible: true
}
PropertyChanges {
target: manipulator; focus: true
}
}
]
state: "noFocus"
//visual area of manipulation (drag, redimension, etc)
MouseArea{
id: manipulator
anchors.fill: parent
onPressed: {
root.state = "focused"
forceActiveFocus(manipulator) //this prevents loosing focus in some especific situations
}
onDoubleClicked: root.state = "innerFocus"
Keys.onEscapePressed: root.state = "noFocus"
}
Rectangle {
id: background
anchors.fill: parent
color: "lightsteelblue";
}
//Inner Component (TextField for example)
InnerComp {
id: innerComp
anchors.fill: parent
Keys.onEscapePressed: root.state = "focused"
}
}
我创建了一个可拖动的自定义组件,以便管理各个快速控制组件的几何形状。
该组件有 2 个部分:
- "Manipulator" 是一个可拖动和可调整大小的矩形
- 位于操纵器中心的内部组件
行为描述:
- 无焦点:默认状态,Manipulator不可见 而且你只能看到内部组件
- Focused:当您单击组件(或尝试拖动它)时,您进入 此状态和操纵器变得可见,但您无法访问 内部组件。禁用按 Escape 键或在组件外部单击(进入状态 1)
- Inner Focus: 当你双击组件 The Manipulator 保持可见,您仍然可以调整大小,但内部 组件具有主要焦点(例如 TextEdit 现在可以是 可编辑)。禁止按下 Escape(进入状态 2)或点击组件外(进入状态 1)
Example of the Component when the Manipulator area is visible
此组件的逻辑类似于桌面环境中文件夹的逻辑(调整大小除外)操纵器将是文件夹本身,内部组件是其名称。
这里是我的 post 我的操纵器的简化版本,我相信它会帮助构建一个答案,(我尝试了几个小时的很多变体,这是那些没有功能的尝试之一)
FocusScope{
id: root
width: 175; height: 25;
focus: true
states: [
State {
name: "noFocus"
when: !manipulator.activeFocus && !innerComp.activeFocus
PropertyChanges {
target: innerComp
enabled: false
}
PropertyChanges {
target: manipulator
visible: false
}
},
State {
name: "focused"
when: manipulator.activeFocus
PropertyChanges {
target: innerComp
enabled: false
}
PropertyChanges {
target: manipulator
visible: true
}
},
State {
name: "innerFocus"
when: innerComp.activeFocus
PropertyChanges {
target: innerComp
enabled: true
}
PropertyChanges {
target: manipulator
visible: true
}
}
]
//visual area of manipulation (drag, redimension, etc)
MouseArea{
id: manipulator
anchors.fill: parent
onDoubleClicked: forceActiveFocus(innerComp) //go to state 3 "innerFocus"
drag.target: manipulator
Keys.onEscapePressed: forceActiveFocus(root) //I don´t think this is the correct to loose focus but I don´t know how to do that
Rectangle {
id: background
anchors.fill: parent
color: "lightsteelblue";
}
}
//Inner Component (TextField for example)
InnerComp {
id: innerComp
anchors.fill: parent
Keys.onEscapePressed: forceActiveFocus(manipulator) //return state 2 "focused"
}
}
我终于找到了解决方案,正如 qt 论坛中有人所建议的那样:
Maybe reverse the dependency, i.e. make the focus depend on the state, not the state depend on the focus?
所以我更改了我的代码,现在可以使用了!
我post这里为那些可能对此感兴趣的人提供解决方案(正如我所说,这是真实代码的简化版本):
Item {
id: root
width: 175; height: 25;
states: [
State {
name: "noFocus"
PropertyChanges {
target: innerComp; enabled: false
}
PropertyChanges {
target: background; visible: false
}
PropertyChanges {
target: manipulator; focus: true
}
},
State {
name: "focused"
PropertyChanges {
target: innerComp; enabled: false
}
PropertyChanges {
target: background; visible: true
}
PropertyChanges {
target: manipulator; focus: true
}
},
State {
name: "innerFocus"
PropertyChanges {
target: innerComp; enabled: true
}
PropertyChanges {
target: background; visible: true
}
PropertyChanges {
target: manipulator; focus: true
}
}
]
state: "noFocus"
//visual area of manipulation (drag, redimension, etc)
MouseArea{
id: manipulator
anchors.fill: parent
onPressed: {
root.state = "focused"
forceActiveFocus(manipulator) //this prevents loosing focus in some especific situations
}
onDoubleClicked: root.state = "innerFocus"
Keys.onEscapePressed: root.state = "noFocus"
}
Rectangle {
id: background
anchors.fill: parent
color: "lightsteelblue";
}
//Inner Component (TextField for example)
InnerComp {
id: innerComp
anchors.fill: parent
Keys.onEscapePressed: root.state = "focused"
}
}