[Solved] Focus, child items, and the end of my wits
-
Hey guys,
I've got an example here where I'm trying to find the "best" way to do this. I've got a QML window with 2 elements: a text box and a listview. You guessed it, it's a search window.
I can easily assign focus programatically to 'scope' by setting scope.focus = true. The problem occurs when I try and figure out a decent way for setting the right focus when clicking on an element in the listview. The only way I can think of this happening in the delegate is by doing some parent.parent.parent.parent gibberish but that is very fragile as it depends on the hierarchy and I'm trying to create a re-usable ListView for my app.
Can anyone think of a pattern that would help me accomplish what I'm trying to do here?
Thanks!
@
import QtQuick 2.1
import QtQuick.Controls 1.0
import QtQuick.Layouts 1.0
import QtGraphicalEffects 1.0ApplicationWindow {
width: 600
height: 300id: win ColumnLayout { anchors.fill: parent Text { Layout.fillWidth: true text: scope.focus ? "ListView has focus" : "ListView doesn't have focus" } TextInput { Layout.fillWidth: true focus: true } /* This is defined somewhere else, independent of the focus scope below */ Component { id: myDelegate Text { text: modelData ? modelData.name + ' (' + modelData.age + ')' : '' width: parent ? parent.width : 0 height: 32 MouseArea { anchors.fill: parent onClicked: { /* how best to set the rectangle enclosing the focus scope to have focus? */ /* This is the effect I want, but without referring to "scope" directly */ /* scope.focus = true */ /* Another way */ var scopehack = parent.parent.parent.parent.parent.parent.parent.parent.parent.parent console.log(scope,scopehack) scopehack.focus = true } } } } /* Actually a Flipable */ Rectangle { id: theflipable color: "#AABBCCDD" Layout.fillWidth: true Layout.fillHeight: true FocusScope { id: scope anchors.fill: parent focus: true Rectangle { anchors.fill: parent color: "transparent" radius: 3 RectangularGlow { anchors.fill: parent visible: scope.activeFocus glowRadius: 10 spread: 0.2 color: "red" cornerRadius: 13 } ScrollView { anchors.fill: parent /* The following two properties allow us to use keyboard navigation within the ListView. See https://bugreports.qt-project.org/browse/QTBUG-31976 */ flickableItem.interactive: true focus: true ListView { anchors.fill: parent boundsBehavior: Flickable.StopAtBounds clip: true focus: true model: ListModel{} delegate: Loader { width: parent.width sourceComponent: myDelegate property variant modelData: model } highlightFollowsCurrentItem: true highlight: Rectangle { width: parent ? parent.width : 0 color: "#3465A4" } highlightMoveDuration: 250 Component.onCompleted: { for(var ii = 0; ii < 250; ++ii) { model.append({'age':ii,'name':'Bopinder ' + ii}) } } } } } } } }
}
@ -
what is the problem with setting the focus via id.focus = true or id.forceActiveFocus()? I don't understand why you don't like that, still better than parent.parent.parent.parent.parent.focus = true I guess :D
Edit: if you don't know the item id at that point why not setting it from the outside to a custom property or something?
@
property Item focusTarget
@
and than from outside just set it to some id you want to get focus when you click on the delegate
@
yourComp.focusTarget = scope
@ -
Because the problem I have is something like this:
@
MyTopLevelWindow {
ColumnLayout {
SearchBar {}
RectangularGlow{...visible: searchResults.activeFocus }
SearchResults{ id: searchResults}
}
@The actual ListView is way down, deep somewhere in the guts of SearchResults because I have a particular implementation I want to use. The focus is assigned to that but the rectangular glow effect is on the searchResults container. Does that make sense?
-
The key points to getting this was:
Understanding that FocusScope is a chain going up ancestry
I needed to was to forceActiveFocus on the child I wanted to get the active focus so it would bubble up to the parent that eventually had the RectangularGlow attached. Simply setting child.focus = true was not sufficient.
Thanks for the quick help Xander84!