Reputation: 13691
While learning QML I stumbled over the problem, that I have to properties that are mutually dependent.
E.g. the user may set a value with a slider, or enter it with a textinput.
While moving the slider, the text in the textinput should be updated while when entering a value in the textinput, the sliders position needs to be adjusted.
Now I have the two properties: the x-value of the slider, and the text in the textinput. I need to convert them into the same format (for example: percent), and update them vice versa. Setting up two bindings would result in a binding loop, which is probably not a good thing to have.
I think, this is a very common problem, so I am sure there is some "gold standard" to solve it. However I can't find a suitable solution.
The only way that comes to my mind, is not to use bindings at all, but handling the signals, that one of the values has changed manually (if I can't overwrite the setter in C++).
Is that all you can do?
Good day to you!
-m-
EDIT: I now tried it with conditionally binding the value of the slider to the percentage value.
The object handle
is the marker on the slider, handleArea
is the MouseArea attached to it, that allows the dragging.
Binding {
target: root
property: 'percent'
value: handle.x / handleBar.width
when: handleArea.drag.active
}
Binding {
target: handle
property: 'x'
value: root.percent * handleBar.width
when: !handleArea.drag.active
}
It works. But is it a good style?
Upvotes: 4
Views: 1975
Reputation: 1728
I would make one property that will store the mutual value. When user inputs text or moves slider they will use a function to update the mutual value. They will also listen to the value change and adjust their value to it.
Here is working example
import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
id: window
visible: true
width: 400
height: 80
title: "Mutual value test"
property double mutualValue: 0
function setMutualValue(value)
{
if (typeof(value) === "string")
{
value = value.replace(",", ".");
value = parseFloat(value)
}
mutualValue = value
}
TextInput {
width: 200
height: 40
validator: DoubleValidator {}
onEditingFinished:
{
focus = false
setMutualValue(text)
}
onFocusChanged:
{
if (text === inputHelp && focus)
text = ""
}
property alias mutualValue: window.mutualValue
onMutualValueChanged: setValue(mutualValue)
property string inputHelp
color: (text === inputHelp && !focus ? "grey" : "black")
function setValue(mutualValue)
{
inputHelp = mutualValue.toFixed(3)
text = inputHelp
}
}
Slider {
x: 200
width: 200
height: 40
onValueChanged: setMutualValue(value)
property alias mutualValue: window.mutualValue
onMutualValueChanged: setValue(mutualValue)
function setValue(mutualValue)
{
value = mutualValue
}
}
Text {
x: (parent.width - width) / 2
y: 40 + (40 - height) / 2
text: "Current value is: " + (window.mutualValue * 100).toFixed(2) + "%"
}
}
Upvotes: 5