Bilateral binding of a C ++ model in QML

I am trying to learn more about QtQuick and QML. My current goal is to understand how to bind data from a C ++ model to my view. So far, I have managed to configure the model in my QML and get the data from the model, but I cannot figure out how to update my data.

How to set up two-way binding for my C ++ model? Below is the code that I have written so far.

message.h

class Message : public QObject { Q_OBJECT Q_PROPERTY(QString author READ getAuthor WRITE setAuthor NOTIFY authorChanged) Q_PROPERTY(QString message READ getMessage WRITE setMessage NOTIFY messageChanged) Q_SIGNALS: void authorChanged(QString author); void messageChanged(QString message); public: Message(QObject *parent = 0); QString getAuthor(); void setAuthor(QString author); QString getMessage(); void setMessage(QString message); private: QString _author; QString _message; }; 

message.cpp

 #include "message.h" Message::Message(QObject *parent) : QObject(parent) { } QString Message::getAuthor() { return _author; } void Message::setAuthor(QString author) { if(author != _author) { _author = author; emit authorChanged(author); } } QString Message::getMessage() { return _message; } void Message::setMessage(QString message) { if(message != _message) { _message = message; emit messageChanged(message); } } 

main.qml

 import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import com.butts.messaging 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: "Test" Message { id: testMessage author: "Batman" message: "Hello World!" } Flow { TextField { text: testMessage.message } Label { text: testMessage.message } } } 

main.cpp

 #include <QGuiApplication> #include <QQmlApplicationEngine> #include "message.h" int main(int argc, char *argv[]) { qmlRegisterType<Message>("com.butts.messaging", 1, 0, "Message"); //Message msg = Message(); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); } 

PS I am a giant noob in this, so feel free to point out any other problems (formatting, standards, etc.). I have in my code, I need to somehow learn lol

Change 1

After reading @derM's answer, I changed my code to achieve what I wanted

 TextField { id: editor //Binding model -> view text: testMessage.message //Binding model <- view Binding { target: testMessage property: "message" value: editor.text } } Label { id: display //Binding model -> view text: testMessage.message } 
+6
source share
1 answer

Binding two words is a difficult question in QML, as it usually works as some kind of assignment.

So, if you bind a property with propertyname: valuetobeboundto and later assign something to propertyname again, that binding will be lost.

As a workaround, there are two ways: using Binding objects or not using binding, but handle all the change-signals properties (which your model emits perfectly correctly) manually.

For the first you can find detailed instructions here. Here they use one Binding -Object for each direction. Well, those Binding will not be overridden by assigning a new Binding .

Consider:

 Row { spacing: 2 Rectangle { id: r0 width: 50 height: 30 } Rectangle { id: r1 width: 50 height: 30 color: b2.pressed ? 'red' : 'blue' } Button { id: b2 } Button { id: b3 onPressed: r1.color = 'black' onReleased: r1.color = 'green' } Binding { target: r0 property: 'color' value: b2.pressed ? 'red' : 'blue' } Binding { target: r0 property: 'color' value: (b3.pressed ? 'black' : 'green') } } 

At the beginning, the value of r1 tied to state b2 , but once b3 been pressed once, r1 will not be updated by clicking on b2 anymore. For r0 update will be performed by two Binding Objects, and therefore Binding will not be lost. However, you can see how the binding works: when the Button state ever changes, the Binding will be updated. Thus, the press AND release of b2 will give signals that will be processed by the first Binding , and the same for press And pass b3 .

Now go to two-way binding. It is important to avoid binding-cycles.

 Row { Button { id: count0 property int count: 0 onClicked: count += 1 text: count } Button { id: count1 property int count: 0 onClicked: count += 1 text: count } Binding { target: count0 property: 'count' value: count1.count } Binding { target: count1 property: 'count' value: count0.count } } 

So far this example is excellent. Changing count0.count will cause a change to count1.count . Now it is checked if count0.count needs updating, but the value is already correct, so the recursion is completed, and no binding occurs.

Change second binding to

  Binding { target: count1 property: 'count' value: count0.count + 1 } 

dramatically changes the situation: now with each change in count0.count you need to increase the value of count1.count . The first Binding then tries to set count0.count to the same value as count1.count , but it is simply not possible for both Binding be completed and no changes are required after the other Binding has worked. This will result in a binding cycle. Fortunately, in QML this is pretty well detected, so blocking can be avoided.

Now there is only one last concern: Consider this component definition:

 // TestObj.qml Item { width: 150 height: 40 property alias color: rect.color Row { spacing: 10 Rectangle { id: rect width: 40 height: 40 radius: 20 color: butt.pressed ? 'green' : 'red' } Button { id: butt text: 'toggle' } } } 

Here we have the internal binding color property, using propertyname: valuetobeboundto -Syntax. This means that the internal binding can be overwritten by any external destination of type color . Replace this binding with a Binding -Object, and you should be fine.

The same would be the other way around: color externally bound to a certain value, and then you process the signal inside and assign a value to it, the external binding will be lost if a Binding object is not created.

This is a general overview. There is more detailed information that can change the behavior of the binding. But I think I showed how you can create a two-way binding and mention some of the pitfalls that may arise.

+12
source

Source: https://habr.com/ru/post/1013316/


All Articles