[Interest] Declaratively handle key presses / navigation differently depending on state (QML)
Elvis Stansvik
elvstone at gmail.com
Thu Mar 31 14:37:51 CEST 2016
Hi,
I'm working on an item representing a number to be edited by the user.
My input is quite limited (only Left, Right and Enter, where Left and
Right is actually the turning of a wheel), so the idea is to let the
user navigating to the item with Left/Right, which will give it focus.
If the user then presses Enter, the item enters and "editing" state.
In the "editing" state, Left and Right will increase/descreas the
number, and pressing Enter again will exit the "editing" state,
returning to the default state ("").
How can I handle key presses differently depending on state without
resorting to procedural code like if/else on the state inside the
onXXXPressed handlers? I thought I'd be able to assign to
Keys.onXXXPressed inside State { PropertyChanges { ... }, but the
property is not recognized there (I'm guessing because it's an
attached property..?).
Also, the KeyNavigation.left/right/etc. is a convenient way to do the
navigation between items, but it seems incompatible with the
Keys.onXXXPressed handlers? I thought I'd be able to skip accepting
the key even in a Keys.onXXXPressed handler, and have it pass through
to the KeyNavigation.xxx handler...? (I can do the navigation with
someItem.forceActiveFocus() instead, but it's more typing and more
error prone).
Below is a working but rather ugly example of two numbers that can be
edited this way. One can navigate between the numbers with Left/Right,
and toggle "editing" mode with Enter (in which Left and Right controls
the number value instead).
How can I make this example more declarative / less ugly? (Besides the
obviously putting things in a reusable component).
Example:
import QtQuick 2.4
import QtQuick.Window 2.2
Window {
width: 800
height: 600
visible: true
Row {
spacing: 30
Column {
Text {
text: "Meters"
}
Text {
id: meters
text: value
font.underline: activeFocus
font.pixelSize: 100
property int value: 3
focus: true
states: [
State {
name: "editing"
PropertyChanges {
target: meters
color: "green"
}
}
]
Keys.onReturnPressed: {
if (state == "")
state = "editing"
else
state = ""
event.accepted = true
}
Keys.onRightPressed: {
if (state == "editing")
value++
else
centimeters.forceActiveFocus()
event.accepted = true
}
Keys.onLeftPressed: {
if (state == "editing")
value--
else
centimeters.forceActiveFocus()
event.accepted = true
}
}
}
Column {
Text {
text: "Centimeters"
}
Text {
id: centimeters
text: value
font.underline: activeFocus
font.pixelSize: 100
property int value: 14
states: [
State {
name: "editing"
PropertyChanges {
target: centimeters
color: "green"
}
}
]
Keys.onReturnPressed: {
if (state == "")
state = "editing"
else
state = ""
event.accepted = true
}
Keys.onRightPressed: {
if (state == "editing")
value++
else
meters.forceActiveFocus()
event.accepted = true
}
Keys.onLeftPressed: {
if (state == "editing")
value--
else
meters.forceActiveFocus()
event.accepted = true
}
}
}
}
}
Thanks for any advice,
Elvis
More information about the Interest
mailing list