Phr*_*ogz 5 qt focus qml qtquickcontrols
我正在创建一个ListView支持多重选择的QML ,并将在我的应用程序中实例化多个。我需要将键盘焦点赋予特定的列表,处理该列表的按键,并根据焦点为选定的行绘制高亮显示。
但是,提供focus=true给ListView委托或ListView本身不会导致activeFocus出现在ListView上,也不会导致触发按键信号。
我创建了一个简单的示例应用程序来显示我的问题:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id:window; visible:true; width:400; height:160; color:'darkgray'
Component {
id: row
Rectangle {
id: root
property int i: index
property bool current: ListView.isCurrentItem
property bool focused: ListView.view.activeFocus
width:parent.width; height:20
color: current ? ( focused ? 'pink' : 'lightblue' ) : 'lightgray'
MouseArea {
anchors.fill: parent
onClicked: {
root.ListView.view.currentIndex = i;
root.ListView.view.focus = true;
}
}
Text { anchors.fill:parent; text:modelData }
}
}
Component {
id: myList
ListView {
delegate: row
width:window.width/2-10; height:window.height; y:5
Keys.onUpPressed: decrementCurrentIndex()
Keys.onDownPressed: incrementCurrentIndex()
}
}
Loader {
sourceComponent:myList; x:5
onLoaded: item.model = ['a','b','c','d']
}
Loader {
sourceComponent:myList; x:window.width/2
onLoaded: item.model = ['1','2','3','4','5']
}
}
Run Code Online (Sandbox Code Playgroud)
单击任一列表都不会将所选行变成粉红色,并且按向上/向下键不会调整选择。
如何将焦点传递给特定对象ListView,使得(a)一次仅一个ListView拥有焦点,并且(b)我可以检测到ListView何时拥有该焦点,并且(c)它允许键盘信号仅适用于该ListView同时集中精力?
我正在使用Qt 5.7,以防万一。
我尝试过的事情失败了:
focus=true在Rectangle而不是ListView上进行设置。focused要监视的属性,ListView.view.focus而不是activeFocus:这允许两个列表同时变为粉红色。通过Qt Quick中的Keyboard Focus读取并将Rectangle或ListView包裹在FocusScope。(这是一件痛苦的事,所有的接口都要一起转发。)
视情况重新阅读该页面,并将两者包装Loader在一个单独的容器中FocusScope。显然,允许同时作为两个ListView进行诅咒具有焦点,这违反了我对文档这一部分的阅读:
在每个焦点范围内,一个对象可能已
Item::focus设置为true。如果设置了多个Itemfocus属性,则最后一个设置焦点的类型将设置focus,而其他项则未设置,这与没有焦点范围的情况类似。
将ListView包裹在项目中,然后将Keys处理程序放在该项目上,然后尝试使该项目集中。
interactive:false在ListView上设置。keyNavigationEnabled:false在ListView上设置。("ListView.keyNavigationEnabled" is not available in QtQuick 2.7尽管Help声明它是在5.7中引入的,但这奇怪地产生了收益,并暗示QtQuick 2.7是正确的import语句。)focus:true我能找到的几乎所有物体,以防万一。注意:我意识到标准ListView使用a highlight来显示选择,并使用键盘导航来调整currentItem。但是,由于我的需求需要同时选择多个项目,因此必须特别管理突出显示和键盘。
编辑:这是一个更简单的测试用例,其行为不像我期望的那样:
import QtQuick 2.7
import QtQuick.Window 2.0
Window {
id:window; visible:true; width:400; height:160; color:'darkgray'
FocusScope {
Rectangle {
width: window.width/2-6; height:window.height-8; x:4; y:4
color: focus ? 'red' : 'gray'
MouseArea { anchors.fill:parent; onClicked:parent.focus=true }
Text { text:'focused'; visible:parent.activeFocus }
Keys.onSpacePressed: console.log('space left')
}
Rectangle {
width: window.width/2-6; height:window.height-8; x:window.width/2+2; y:4
color: focus ? 'red' : 'gray'
MouseArea { anchors.fill:parent; onClicked:parent.focus=true }
Text { text:'focused'; visible:parent.activeFocus }
Keys.onSpacePressed: console.log('space right')
}
}
}
Run Code Online (Sandbox Code Playgroud)
单击每个矩形使其变为红色,并且在任何给定时间只允许一个为红色。(这很好。)但是,由于“矩形”没有显示,因此不会显示“聚焦”文本activeFocus。此外,space当任何一个都聚焦时,按永不记录消息。
编辑2:哇。如果我删除FocusScope,它会按预期工作:焦点仍然是排他的,activeFocus被授予并且space工作正常。也许我上面的问题是,因为ListView是FocusScope(根据文档)。
编辑3:Per Mitch在下面的注释中,focus:true在上设置FocusScope也可以使所有内容与FocusScope一起正常工作。但是,按照我在下面的回答(以及Mitch的评论),FocusScope并不是使我的两个简化示例应用程序都能正常工作所必需的。
如果您在原始示例中打印了活动焦点项目
onActiveFocusItemChanged: print(activeFocusItem)
Run Code Online (Sandbox Code Playgroud)
您会看到没有一个装载机能够集中注意力;它始终是窗口的根项。
如果您设置focus: true了其中一个装载机,那么它将具有重点:
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
id: window
visible: true
width: 400
height: 160
color: 'darkgray'
onActiveFocusItemChanged: print(activeFocusItem)
Component {
id: row
Rectangle {
id: root
property int i: index
property bool current: ListView.isCurrentItem
property bool focused: ListView.view.activeFocus
width: parent.width
height: 20
color: current ? (focused ? 'pink' : 'lightblue') : 'lightgray'
MouseArea {
anchors.fill: parent
onClicked: {
root.ListView.view.currentIndex = i
root.ListView.view.focus = true
}
}
Text {
anchors.fill: parent
text: modelData
}
}
}
Component {
id: myList
ListView {
delegate: row
width: window.width / 2 - 10
height: window.height
y: 5
Keys.onUpPressed: decrementCurrentIndex()
Keys.onDownPressed: incrementCurrentIndex()
}
}
Loader {
objectName: "loader1"
sourceComponent: myList
focus: true
x: 5
onLoaded: item.model = ['a', 'b', 'c', 'd']
}
Loader {
objectName: "loader2"
sourceComponent: myList
x: window.width / 2
onLoaded: item.model = ['1', '2', '3', '4', '5']
}
}
Run Code Online (Sandbox Code Playgroud)
但是,现在,当您单击第二个视图的委托时,第二个视图将不再具有焦点。如果我们宣布它们都具有焦点,那么我们将失去对最终目标的控制。实际上,即使我们确实声明它们都具有焦点,单击第二个视图的委托也不会赋予该视图主动焦点,因为当第一个加载器获得焦点时,它已经失去了焦点。换句话说,要使其正常工作,您还必须给予加载程序以焦点,这违背了将漂亮的少量捆绑代表组件的全部目的:
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
id: window
visible: true
width: 400
height: 160
color: 'darkgray'
onActiveFocusItemChanged: print(activeFocusItem)
Component {
id: row
Rectangle {
id: root
property int i: index
property bool current: ListView.isCurrentItem
property bool focused: ListView.view.activeFocus
width: parent.width
height: 20
color: current ? (focused ? 'pink' : 'lightblue') : 'lightgray'
MouseArea {
anchors.fill: parent
onClicked: {
root.ListView.view.currentIndex = i
root.ListView.view.parent.focus = true
root.ListView.view.focus = true
}
}
Text {
anchors.fill: parent
text: modelData
}
}
}
Component {
id: myList
ListView {
delegate: row
width: window.width / 2 - 10
height: window.height
y: 5
Keys.onUpPressed: decrementCurrentIndex()
Keys.onDownPressed: incrementCurrentIndex()
}
}
Loader {
objectName: "loader1"
sourceComponent: myList
x: 5
onLoaded: item.model = ['a', 'b', 'c', 'd']
}
Loader {
objectName: "loader2"
sourceComponent: myList
x: window.width / 2
onLoaded: item.model = ['1', '2', '3', '4', '5']
}
}
Run Code Online (Sandbox Code Playgroud)
在这一点上,我只是放弃并强迫积极关注:
import QtQuick 2.7
import QtQuick.Window 2.2
Window {
id: window
visible: true
width: 400
height: 160
color: 'darkgray'
onActiveFocusItemChanged: print(activeFocusItem)
Component {
id: row
Rectangle {
id: root
objectName: ListView.view.objectName + "Rectangle" + index
property int i: index
property bool current: ListView.isCurrentItem
property bool focused: ListView.view.activeFocus
width: parent.width
height: 20
color: current ? (focused ? 'pink' : 'lightblue') : 'lightgray'
MouseArea {
anchors.fill: parent
onClicked: {
root.ListView.view.currentIndex = i
root.ListView.view.forceActiveFocus()
}
}
Text {
anchors.fill: parent
text: modelData
}
}
}
Component {
id: myList
ListView {
objectName: parent.objectName + "ListView"
delegate: row
width: window.width / 2 - 10
height: window.height
y: 5
Keys.onUpPressed: decrementCurrentIndex()
Keys.onDownPressed: incrementCurrentIndex()
}
}
Loader {
id: loader1
objectName: "loader1"
sourceComponent: myList
x: 5
onLoaded: item.model = ['a', 'b', 'c', 'd']
}
Loader {
objectName: "loader2"
sourceComponent: myList
x: window.width / 2
onLoaded: item.model = ['1', '2', '3', '4', '5']
}
}
Run Code Online (Sandbox Code Playgroud)
我真的不喜欢聚焦系统。我并不是说我可以提出更好的建议,但这并不容易使用。