How to bind TextInput.text to QString property in two ways?



  • Hello,
    I try to bind a QML TextInput to a QString-property of a C++-QObject. My expectation is that the text in the TextInput is updated whenever the NOTIFY-signal of that property is fired AND that the setter of that property is called whenever the text in the TextInput is changed by the user. However, I can only see the first behaviour. I created a small example that has a QLineEdit and a QDeclarativeView in a layout. The lineEdit is exposed to the QML-file using a context property. Now I bind to the property using this QML-file:

    @
    import Qt 4.7
    Rectangle {
    width: 240
    height: 320

    TextInput {
        text: lineEdit.text
        anchors.fill: parent
    }
    

    }@

    Whenever I change the text in the QLineEdit now, the TextInput within the declarative view is updated. However, when I change the test in the TextInput, nothing happens. I expected that the QLineEdit would be updated as well. Is this intended behavior? If yes, how to keep both in sync? Shouldn't a declarative binding work in two ways?



  • take a look at this example on forum nokia: "http://wiki.forum.nokia.com/index.php/CS001625_-Connecting_Qt_signal_to_QML_function":http://wiki.forum.nokia.com/index.php/CS001625-_Connecting_Qt_signal_to_QML_function



  • Thank you but this does not help because it is just an alternate way to do the part that already works. I want the C++ lineedit to be updated from the QML one. And I actually want to do it in a declarative way and not an imperative way.



  • Hi,

    QML currently only supports "one-way" bindings. You can use the "Binding":http://doc.qt.nokia.com/4.7/qml-binding.html element if you want to bind lineEdit.text to the text of the TextInput as well.

    @
    import Qt 4.7
    Rectangle {
    width: 240
    height: 320

    TextInput {
        id: input
        text: lineEdit.text
        anchors.fill: parent
    }
    Binding {
        target: lineEdit
        property: "text"
        value: input.text
    }
    

    }
    @

    Regards,
    Michael



  • Thank you. This is exactly the information I was looking for.



  • Hi,

    Doing this will generate a console warning:

    QML TextInput: Binding loop detected for property "text"

    It works nevertheless but I don't like warnings.

    Any ideas?

    Regards

    Nils



  • File a bugreport :-)



  • Well, it actually is a binding loop. However it does not do any harm as long as the setter on the C++ side is implemented correctly.



  • I meant it more as: file a bug report with a suggestion to make two way bindings possible :-)



  • [quote author="njeisecke" date="1305030760"]Hi,

    Doing this will generate a console warning:

    QML TextInput: Binding loop detected for property "text"

    It works nevertheless but I don't like warnings.

    Any ideas?
    [/quote]

    Hi Nils,

    Is it the exact snippet above (with a QLineEdit in C++) you are testing or something else?

    Typically this warning is avoided via the C++ implementation of the setter, e.g. setText() will be implemented to only emit the NOTIFY signal if the property actually changes. I thought in this case both TextInput and QLineEdit would have done this, though (so there might be something else at play here that I've missed).

    Regards,
    Michael



  • Are you suggesting that Qt Quick is at runtime able to analyze if the (C++) objects block emitting a changed signal if you set the same value on a property? And that they only should give the Binding Loop warning if they don't block the signal? That would be pretty cool! But I think that is unlikely. I think it is a warning because it can not be detected if the signal is emitted. If it could, it would (should) be an error instead.



  • Hi Michael,

    my setter was on the c++ side and indeed wrongly implemented (stupid me).

    With an implementation like this everything works as expected:

    @
    void MyObject::setValue(const QString &value)
    {
    // this avoids the (absolutely correct) warning
    if (m_value == value)
    return;

    m_value = value;
    emit valueChanged():
    }
    @

    So actually there seems to be some runtime analysis. Cool ;-)



  • Does implementing it like this fix the warning? That would be awesome!
    If so, then perhaps the warning should be an error instead?



  • Yes it does, I've just commented out the check and the warning appears.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.