Using a Qml component property for read/write access of a value without killing bindings
-
Please have a look at the following code:
main.qml
@
import QtQuick 1.0Rectangle {
width: 500
height: 200Column {
Text { text: "Slider 1 " + slider1.value }
Slider { id: slider1; value: slider2.value; minimum: 0; maximum: 10; }
Text { text: "Slider 2 (drag me to set value 1, too)" + slider2.value }
Slider { id: slider2; minimum: 0; maximum: 10; }Text { text: "Text 1 " + text1.text } TextInput { height: 20; width: 200; id: text1; text: text2.text; } Text { text: "Text 2 (text entered here will show in Text 1, too)" + text2.text } TextInput { height: 20; width: 200; id: text2 }
}
}
@Slider.qml
@
import QtQuick 1.0Item {
property alias value: slider.value
property alias minimum: slider.minimum
property alias maximum: slider.maximum
width: slider.width
height: slider.heightItem {
id: slider; width: 400; height: 16// value is read/write. property real value: 1 onValueChanged: updatePos(); property real maximum: 1 property real minimum: 1 property int xMax: width - handle.width - 4 onXMaxChanged: updatePos(); onMinimumChanged: updatePos(); function updatePos() { console.log("update pos") if (maximum > minimum) { var pos = 2 + (value - minimum) * slider.xMax / (maximum - minimum); pos = Math.min(pos, width - handle.width - 2); pos = Math.max(pos, 2); handle.x = pos; } else { handle.x = 2; } } Rectangle { anchors.fill: parent border.color: "white"; border.width: 0; radius: 8 gradient: Gradient { GradientStop { position: 0.0; color: "#66343434" } GradientStop { position: 1.0; color: "#66000000" } } } Rectangle { id: handle; smooth: true y: 2; width: 30; height: slider.height-4; radius: 6 gradient: Gradient { GradientStop { position: 0.0; color: "lightgray" } GradientStop { position: 1.0; color: "gray" } } MouseArea { id: mouse anchors.fill: parent; drag.target: parent drag.axis: Drag.XAxis; drag.minimumX: 2; drag.maximumX: slider.xMax+2 onPositionChanged: { value = (slider.maximum - slider.minimum) * (handle.x-2) / slider.xMax + slider.minimum; } } }
}
}
@The slider is basically taken from some example.
Now please try the following:
- Use slider2 to adjust the value
- See how slider1 will display the same value as slide2 (due to the binding in main.qml:9)
- Now use slider1 to adjust the value
- Now use slider2 again => binding is removed (due to Slider.qml:56)
This seems to be a problem with bindings for all components written in Qml that use the same property for read and write access of some value.
The interesting thing is that I tried to do basically the same with a TextInput instead of the custom slider. And guess what, it works there. The binding is not lost.
Now TextInput is a component implemented in c++. So it does not actually assign a value to its text property but rather has a getter method and a notifier signal.
My question now is: How can i achieve this behaviour for Qml components too?
Thanks
Nils
-
Hi Andre,
yes. But I cannot see how Binding solves this problem.
I've also had a look at some of the Meego/Symbian components. They do basically the same as the Slider example, killing any binding as soon as the component modifies its own value property.
See http://qt.gitorious.org/qt-components/qt-components/blobs/master/src/meego/CheckBox.qml.
My motivation for doing this kind of stuff is:
- I have a settings object containing some settings
- I want to bind the component's value property to the value of the settings object
- Changes in the settings object's values (from somewhere else) will now automatically update the Qml components
- Of course this only works as long as the binding exists
This is somewhat related to: http://developer.qt.nokia.com/forums/viewthread/1779/
I was hoping the binding mechanism would simplify the old way of doing stuff like this:
@
void MyDialog::settingsToWidgets()
{
ui->textEdit->setText(m_settings.someText());
ui->slider->setValue(m_settings.someValue());
}void MyDialog::widgetsToSettings()
{
m_settings.setSomeText(ui->textEdit->text());
m_settings.setSomeValue(ui->slider->value());
}
@Thank you
Nils
-
In Qt Quick 1.1 you can establish binding in imperative JS code... See http://developer.qt.nokia.com/forums/viewthread/5494/