Correct syntax for setting C++ property in QML
-
Hi all -
I've implemented a display with a MouseArea that, when clicked, change the value of a property defined in a C++ class.
class Opmode : public QObject { Q_OBJECT Q_PROPERTY(ModeEnum mode READ mode WRITE setMode NOTIFY modeChanged); public: explicit Opmode(QObject *parent = nullptr); ModeEnum mode() { return m_opmode; } void setMode(const ModeEnum &m); ...
In my QML:
MouseArea { anchors.fill: parent onClicked: { control.checked = true opMode.mode = mode <== this works // opMode.setMode(mode) <== this doesn't ...
I guess I've never done this before. Is there some reason that I can't use the setMode function in the class? And, is my assignment OK? It seems to work, but I'd like to know for sure.
Thanks...
-
Hi all -
I've implemented a display with a MouseArea that, when clicked, change the value of a property defined in a C++ class.
class Opmode : public QObject { Q_OBJECT Q_PROPERTY(ModeEnum mode READ mode WRITE setMode NOTIFY modeChanged); public: explicit Opmode(QObject *parent = nullptr); ModeEnum mode() { return m_opmode; } void setMode(const ModeEnum &m); ...
In my QML:
MouseArea { anchors.fill: parent onClicked: { control.checked = true opMode.mode = mode <== this works // opMode.setMode(mode) <== this doesn't ...
I guess I've never done this before. Is there some reason that I can't use the setMode function in the class? And, is my assignment OK? It seems to work, but I'd like to know for sure.
Thanks...
@mzimmers you aren't meant to call the getter and setter of a Q_PROPERTY from the QML side. Your assignment is ok, it's how it's supposed to be.
For completeness, if you make your
setMode
a (public)slot or mark it explicitly with the Q_INVOKAVBLE makro, then you can also call the setter from QML -
@mzimmers you aren't meant to call the getter and setter of a Q_PROPERTY from the QML side. Your assignment is ok, it's how it's supposed to be.
For completeness, if you make your
setMode
a (public)slot or mark it explicitly with the Q_INVOKAVBLE makro, then you can also call the setter from QML@J-Hilk said in Correct syntax for setting C++ property in QML:
For completeness, if you make your setMode a (public)slot or mark it explicitly with the Q_INVOKAVBLE makro, then you can also call the setter from QML
Well, setMode is in my Q_INVOKABLE macro. It's not declared as a slot, but I thought there was nothing special about slot functions?
EDIT:
I just tried marking setMode() as a slot, and now that line works. Thanks for the help, guys, though I'm not sure I fully understand why it needs to be declared a slot.
-
@J-Hilk said in Correct syntax for setting C++ property in QML:
For completeness, if you make your setMode a (public)slot or mark it explicitly with the Q_INVOKAVBLE makro, then you can also call the setter from QML
Well, setMode is in my Q_INVOKABLE macro. It's not declared as a slot, but I thought there was nothing special about slot functions?
EDIT:
I just tried marking setMode() as a slot, and now that line works. Thanks for the help, guys, though I'm not sure I fully understand why it needs to be declared a slot.
@mzimmers True. Here the setter may be used by other C++ classes. In QML, it is not needed in this case. Also do not define it if it is not used.
I often define variables like the following when the setter is not used.
Q_PROPERTY( bool android MEMBER m_android CONSTANT )
Q_PROPERTY( bool charging MEMBER m_charging NOTIFY chargingChanged ) -
@mzimmers True. Here the setter may be used by other C++ classes. In QML, it is not needed in this case. Also do not define it if it is not used.
I often define variables like the following when the setter is not used.
Q_PROPERTY( bool android MEMBER m_android CONSTANT )
Q_PROPERTY( bool charging MEMBER m_charging NOTIFY chargingChanged ) -
From a best practices standpoint, is one of these preferred over the other?
opMode.mode = mode opMode.setMode(mode)
@mzimmers If you still remember encapsulation of C++, opMode.setMode(mode) is preferred in C++ classes. But in QML, encapsulation has been sort of dropped. Any call from C++ classes use setter. In QML, you can use opMode.mode = mode. However, if this change or opMode.mode is used in some other QML files and you need to send out modeChanged signal, you will need opMode.setMode(mode).
-
From a best practices standpoint, is one of these preferred over the other?
opMode.mode = mode opMode.setMode(mode)
@mzimmers My previous answer may not be right completely. You can not call opMode.setMode(mode) because mode is not registered as type? Is it an enum? If yes, define it
https://forum.qt.io/topic/109031/passing-enum-into-c-function-like-parameter-from-qml-how/8opMode.mode = mode /* no notification /
opMode.setMode(mode) / with notification since emit modeChanged is defined in this function *//* qml supported types */
https://doc.qt.io/qt-6/qtqml-cppintegration-data.html -
From a best practices standpoint, is one of these preferred over the other?
opMode.mode = mode opMode.setMode(mode)
@mzimmers said in Correct syntax for setting C++ property in QML:
From a best practices standpoint, is one of these preferred over the other?
opMode.mode = mode opMode.setMode(mode)
opMode.mode = mode
is. Prefer to use properties when possible.Contrary to what JoeCFD is saying, this is more encapsulated than calling setMode. You are not acting on the C++ variable anyway, you are going through the QML engine and it can make use of this for stuff like behaviors for example.
When doing
opMode.mode = mode
themodeChanged
signal WILL be called (provided that your WRITE method is correctly coded). -
For the sake of completeness in this topic, I think I've covered all my other bases. I've defined the enums appropriately:
// opmode.h namespace OpmodeNS { Q_NAMESPACE typedef enum ModeEnum { Standard, Saving, Boost, Service } opmodeEnums; Q_ENUM_NS(ModeEnum) }
and registered it accordingly:
// main.cpp // register the Opmode enums so they can be used in QML. qmlRegisterUncreatableMetaObject( OpmodeNS::staticMetaObject, // meta object created by Q_NAMESPACE macro "Opmodes", // import statement (can be any string) 1, 0, // major and minor version of the import "OpModes", // name used in QML (does not have to match C++ name) "Error: only enums" // error in case someone tries to create an object );
And my WRITE method:
// opmode.cpp void Opmode::setMode(const ModeEnum &m) { if (m != m_opmode) { m_opmode = m; emit modeChanged(m_opmode); } }
Thanks to everyone for the input on this; as usual, it's been educational.
-
@mzimmers said in Correct syntax for setting C++ property in QML:
From a best practices standpoint, is one of these preferred over the other?
opMode.mode = mode opMode.setMode(mode)
opMode.mode = mode
is. Prefer to use properties when possible.Contrary to what JoeCFD is saying, this is more encapsulated than calling setMode. You are not acting on the C++ variable anyway, you are going through the QML engine and it can make use of this for stuff like behaviors for example.
When doing
opMode.mode = mode
themodeChanged
signal WILL be called (provided that your WRITE method is correctly coded).@GrecKo
In C++ the way of mode access in QML like opMode.mode = mode is like public access and is not preferred in C++. That is what I meant.
Contrary to what JoeCFD is saying, this is more encapsulated than calling setMode. You are not acting on the C++ variable anyway, you are going through the QML engine and it can make use of this for stuff like behaviors for example.Good to know.
When doing opMode.mode = mode the modeChanged signal WILL be called (provided that your WRITE method is correctly coded).