Laurent Michel
Laurent Michel

Reputation: 1321

How to make QML TextField binding work under Android?

I am currently trying to write a QML/C++ application for Android. Somewhere in my code, I have a class that looks like this:

class MyClass : public QObject
{
  Q_OBJECT

  Q_PROPERTY(QString prop READ prop WRITE setProp NOTIFY propChanged)

public:
  explicit MyClass(QObject* a_Parent = 0);

  QString prop() const
  {
    return m_Prop;
  }

  void setProp(const QString& a_Value)
  {
    m_Prop = a_Value;
    emit propChanged();
  }

signals:
  void propChanged();

private:
  QString m_Prop;
};

Somwhere in my QML stuff, I have an Item defined in the following way:

ColumnLayout {
  TextField {
    id: myField
    placeholderText: qsTr("Enter text")
    Layout.fillWidth: true
    Binding {
      target: myClass
      property: "prop"
      value: myField.text
    }
}

Of course, I did everything necessary to make the object myClass of type MyClass shared between C++ and QML (as a context property).

Now, the problem is the following: whatever I'm typing in the above textfield, under Android, the last word is never communicated from myField.text to MyClass.m_Prop. For example, if I type the text "I am not happy with this TextField" in the TextField, then myClass.m_Prop will contain "I am not happy with this". However, if I type "I am not happy with this TextField " (notice the space) and then remove the last space, then the desired string is stored in the m_Prop variable.

Strange is, that this works perfectly fine under Linux. Can someone tell me what I am missing here? I am working with Qt 5.7 and Android 6.0.

Thanks for your help ...

Upvotes: 2

Views: 1382

Answers (1)

Laurent Michel
Laurent Michel

Reputation: 1321

As far as I understand the comments to my question, I have a few possibilities to solve this problem. The simplest one is to modify my QML item like this:

ColumnLayout {
  TextField {
    id: myField
    placeholderText: qsTr("Enter text")
    Layout.fillWidth: true
    Binding {
      target: myClass
      property: "prop"
      value: myField.displayText
    }
}

If I didn't want to allow predictive text input, then I could just add the

inputMethodHints: Qt.ImhNoPredictiveText

on the TextField. In my case, I want predictive text input.

Last, I could call QInputMethod::commit() when I click the button "Done" of my application, which will commit the displayed text on Android and then use the committed text in MyClass. In this case, I should not use QML's Binding feature. Instead, I should just commit the data to Android and then communicate my QML data to myClass.

The simplest solution that best fits QML philosophy is probably to use displayText instead of text, which is the solution I am choosing.

Upvotes: 6

Related Questions