Reputation: 11408
I've a two column layout with a ListView in the left column. With the Left/Right Keys I can change focus between the two parts of the app.
The active focus of the left column is delegated to the ListView and from there straight to one of it's rows.
How can I check whether the ListView or one of it's children has focus?
import QtQuick 1.1
FocusScope {
width: 960
height: 540
id: app
focus: true
FocusScope {
id: leftColumn
KeyNavigation.right: rightColumn
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: parent.top
width: 250
focus: true
Rectangle {
id: leftBackgroundColor
anchors.fill: parent
color: contactsList.activeFocus ? "red" : "#E6E6E6"
ListView {
id: contactsList
interactive: true
anchors.fill: parent
focus: true
delegate: Text {
text: name
font.bold: activeFocus
}
model: ListModel {
ListElement { name: "Simon" }
ListElement { name: "Mary" }
ListElement { name: "Jack" }
ListElement { name: "Frank" }
}
}
}
}
FocusScope {
id: rightColumn
KeyNavigation.left: leftColumn
anchors.left: leftColumn.right
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
onFocusChanged: console.log("Right focus changed: " + focus + "/" + activeFocus)
Rectangle {
id: rightBackgroundColor
anchors.fill: parent
focus: true
color: activeFocus ? "red" : "#b3b3b3"
}
}
}
Upvotes: 2
Views: 14161
Reputation: 881
I know that this is an old question, but I think it still deserves a proper explanation, as the same model of focus is still used in QtQuick 2.
How can I check whether the ListView or one of it's children has focus?
The central problem here is that you appear to be a little confused about the meanings of the two focus properties (and that's understandable, it's a bit non-obvious).
To see if a FocusScope (or any of its children) has focus right now, you want to check the Item::activeFocus
property on it. This means "either I, or one of my children has focus right now", and it's recursively cleared from a FocusScope when focus is moved to another FocusScope.
On the other hand, Item::focus
is a request for focus, not information about the current state, so you should not be binding other values on it (e.g. color: foo.focus ? "black" : "red"
) to it, unless you want to check whether or not the item is capable of gaining focus at some point in the future, not whether it has focus right now.
That explains why you can have something with Item::focus
true, while it doesn't actually have focus -- it's not that the signal is missing, it's that you were misusing the property to mean something it isn't.
So, you want something like this:
Rectangle {
id: leftBackgroundColor
anchors.fill: parent
color: leftColumn.activeFocus ? "red" : "#E6E6E6"
}
...
Rectangle {
id: rightBackgroundColor
anchors.fill: parent
focus: true
color: rightColumn.activeFocus ? "red" : "#b3b3b3"
}
Upvotes: 2
Reputation: 11408
I think I found a workaround:
onActiveFocusChanged: { focusChanged(focus) }
This emits the focusChanged signal whenever the active focus changes. Using this, the property bindings (like color: parent.focus ? "red" : "#E6E6E6") work as well.
Full test code:
import QtQuick 1.1
FocusScope {
width: 960
height: 540
id: app
focus: true
FocusScope {
id: leftColumn
KeyNavigation.right: rightColumn
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.top: parent.top
width: 250
onActiveFocusChanged: { focusChanged(focus) }
Rectangle {
id: leftBackgroundColor
anchors.fill: parent
color: parent.focus ? "red" : "#E6E6E6"
ListView {
id: contactsList
interactive: true
anchors.fill: parent
focus: true
delegate: Text {
text: name
font.bold: activeFocus
}
model: ListModel {
ListElement { name: "Simon" }
ListElement { name: "Mary" }
ListElement { name: "Jack" }
ListElement { name: "Frank" }
}
}
}
}
FocusScope {
id: rightColumn
focus: true
KeyNavigation.left: leftColumn
anchors.left: leftColumn.right
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: parent.top
onActiveFocusChanged: { focusChanged(focus) }
Rectangle {
id: rightBackgroundColor
anchors.fill: parent
focus: true
color: activeFocus ? "red" : "#b3b3b3"
}
}
}
Upvotes: 3
Reputation: 5289
You are creating trouble for yourself in this code. Only one element can have focus at any given time so if you have every element's focus property set to true its not especially clear which element has focus when it is rendered(I believe its the last element rendered that has focus set). As to figuring out which element has focus you can't request the current focused element. What you can do is hookup a listener to the onFocusChanged event that exists on the elements to perform actions when that object gains/loses focus. A better question might be why do you care who has focus?
Upvotes: 0