Integrating QML and C++
-
Hi all,
As the first step for being familiar with the technique integrating QML and C++ I went for this example.
I ran it and I have some questions:-
Why do we need a Q_PROPERTY macro there? Yeah, I know that it's said that it declares a property that could be accessed from QML. But we have two functions for both reading and writing to the data member. (userName) We could have declared a data member named, say, userName, and haven't declared a a Q_PROPERTY macro seemingly.
-
The program does almost nothing and just gets texts! Emitting the signal won't work either there.
-
-
Hi all,
As the first step for being familiar with the technique integrating QML and C++ I went for this example.
I ran it and I have some questions:-
Why do we need a Q_PROPERTY macro there? Yeah, I know that it's said that it declares a property that could be accessed from QML. But we have two functions for both reading and writing to the data member. (userName) We could have declared a data member named, say, userName, and haven't declared a a Q_PROPERTY macro seemingly.
-
The program does almost nothing and just gets texts! Emitting the signal won't work either there.
@tomy said in Integrating QML and C++:
We could have declared a data member named
You mean a public member? Well, it is called encapsulation in object oriented languages: you make your data fields private and provide read/write methods where you can control the access (for example refuse changes which should not be possible).
-
-
Hi all,
As the first step for being familiar with the technique integrating QML and C++ I went for this example.
I ran it and I have some questions:-
Why do we need a Q_PROPERTY macro there? Yeah, I know that it's said that it declares a property that could be accessed from QML. But we have two functions for both reading and writing to the data member. (userName) We could have declared a data member named, say, userName, and haven't declared a a Q_PROPERTY macro seemingly.
-
The program does almost nothing and just gets texts! Emitting the signal won't work either there.
@tomy said in Integrating QML and C++:
I ran it and I have some questions:
-
Why do we need a Q_PROPERTY macro there? Yeah, I know that it's said that it declares a property that could be accessed from QML. But we have two functions for both reading and writing to the data member. (userName) We could have declared a data member named, say, userName, and haven't declared a a Q_PROPERTY macro seemingly.
-
The program does almost nothing and just gets texts! Emitting the signal won't work either there.
hi tomy
let's see if I can makes a bit more clear for you, with my (limited) knowledge.
first of lets change the example q_propery a bit so one does not get confused with the nomenclature
//original Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged) //new Q_PROPERTY(QString userName READ getUserName WRITE setUserName NOTIFY userNameChanged)
On the QML-Side the property is named
userName
you can do property bindings with it:userName : "FixesText" //or userName: otherStringProperty
if a bound property is changed the signal
userNameChanged
is emittedon QML-Side you can attach to that via
onUserNameChanged: console.log("Username was changed", userName)
on cpp side via QObject:::connect()
connect(this, myClass::userNameChanged, [=]{qDebug() << "Username was changed" << getUserName();});
the signal is always emitted on both sides, QML and cpp
assigning a new string to the property on qml side
userName = "New Username"
actually envokes the cpp function
setUserName
If you envoke setUserName from the cpp class,
userNameChanged
is emitted, if the string actually is different from before:If a QML property is bound to userName, QML will call
getUserName
to get the new string and update all bound properties.emitting userNameChanged() from cpp without actually chaning
m_userName
will have no visible change in your QML code, but it will update all bound properties.chaning
m_userName
without emitting the signaluserNameChanged
on cpp side will not update the QML part -
-
@tomy said in Integrating QML and C++:
We could have declared a data member named
You mean a public member? Well, it is called encapsulation in object oriented languages: you make your data fields private and provide read/write methods where you can control the access (for example refuse changes which should not be possible).
-
@tomy said in Integrating QML and C++:
I ran it and I have some questions:
-
Why do we need a Q_PROPERTY macro there? Yeah, I know that it's said that it declares a property that could be accessed from QML. But we have two functions for both reading and writing to the data member. (userName) We could have declared a data member named, say, userName, and haven't declared a a Q_PROPERTY macro seemingly.
-
The program does almost nothing and just gets texts! Emitting the signal won't work either there.
hi tomy
let's see if I can makes a bit more clear for you, with my (limited) knowledge.
first of lets change the example q_propery a bit so one does not get confused with the nomenclature
//original Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged) //new Q_PROPERTY(QString userName READ getUserName WRITE setUserName NOTIFY userNameChanged)
On the QML-Side the property is named
userName
you can do property bindings with it:userName : "FixesText" //or userName: otherStringProperty
if a bound property is changed the signal
userNameChanged
is emittedon QML-Side you can attach to that via
onUserNameChanged: console.log("Username was changed", userName)
on cpp side via QObject:::connect()
connect(this, myClass::userNameChanged, [=]{qDebug() << "Username was changed" << getUserName();});
the signal is always emitted on both sides, QML and cpp
assigning a new string to the property on qml side
userName = "New Username"
actually envokes the cpp function
setUserName
If you envoke setUserName from the cpp class,
userNameChanged
is emitted, if the string actually is different from before:If a QML property is bound to userName, QML will call
getUserName
to get the new string and update all bound properties.emitting userNameChanged() from cpp without actually chaning
m_userName
will have no visible change in your QML code, but it will update all bound properties.chaning
m_userName
without emitting the signaluserNameChanged
on cpp side will not update the QML partHi J.Hilk, thank you very much.
//original Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged) //new Q_PROPERTY(QString userName READ getUserName WRITE setUserName NOTIFY userNameChanged)
On the QML-Side the property is named
userName
So declaring a Q_PROPERTY is the only way to have a property/variable inside the C++ code and also have access to it from QML side and declaring such a property inside the private or even public area (on the C++ side) doesn't provide us with accessing it from the QML side, yes?
if a bound property is changed the signal
userNameChanged
is emittedLike here:
onTextChanged: backend.userName = text
Yeah?on QML-Side you can attach to that via
onUserNameChanged: console.log("Username was changed", userName)
I used it inside the BackEnd:
BackEnd { id: backend onUserNameChanged: console.log("Username was changed", userName) }
If a QML property is bound to userName, QML will call
getUserName
to get the new string and update all bound properties.Like here?
text: backend.userName
-
-
Hi J.Hilk, thank you very much.
//original Q_PROPERTY(QString userName READ userName WRITE setUserName NOTIFY userNameChanged) //new Q_PROPERTY(QString userName READ getUserName WRITE setUserName NOTIFY userNameChanged)
On the QML-Side the property is named
userName
So declaring a Q_PROPERTY is the only way to have a property/variable inside the C++ code and also have access to it from QML side and declaring such a property inside the private or even public area (on the C++ side) doesn't provide us with accessing it from the QML side, yes?
if a bound property is changed the signal
userNameChanged
is emittedLike here:
onTextChanged: backend.userName = text
Yeah?on QML-Side you can attach to that via
onUserNameChanged: console.log("Username was changed", userName)
I used it inside the BackEnd:
BackEnd { id: backend onUserNameChanged: console.log("Username was changed", userName) }
If a QML property is bound to userName, QML will call
getUserName
to get the new string and update all bound properties.Like here?
text: backend.userName
Hi @tomy
So declaring a Q_PROPERTY is the only way to have a property/variable inside the C++ code and also have access to it from QML side and declaring such a property inside the private or even public area (on the C++ side) doesn't provide us with accessing it from the QML side, yes?
Q_Property is a Macro so I would asume it does not matter if its in the public, or private section of your class. But your read &write functions defenitly have to be public.
It is not the only way, but the most convenient. I know of one more way to get a value from a cpp class:
//in your header public: Q_INVOKABLE int getIntValueFromCpp(){return qrand();} //In qml val intValue = myCppObject.getIntValueFromCpp()
if a bound property is changed the signal
userNameChanged
is emittedLike here:
onTextChanged: backend.userName = text
Yeah?Yes as soon as text changes the in your backend setUserName is invoked, thanks to the Q_PROPERTY makro, and because of the body of setUserName userNameChanged is emitted if text != userName
If a QML property is bound to userName, QML will call
getUserName
to get the new string and update all bound properties.Like here?
text: backend.userName
yes:
:
= Propertybinding
=
= Asigning a Valuekeep in mind, asigning a value (=) will destroy a previous binding.