Sometimes, for whatever reason, we want to modify the properties of a QML object through C/C++ scripting. Qt’s QML engine actually supports this and it allows you to register your QML objects as C/C++ types, however, this is often not well-explained.
For example, I created a label in QML and I want to change its text occasionally. In order for me to expose the label object to C/C++, I created a C/C++ class called MyClass which extended from QObject class.
class MyClass : public QObject
// Object pointer
explicit MyClass(QObject *parent = 0);
// Must call Q_INVOKABLE so that this function can be used in QML
Q_INVOKABLE void SetMyObject(QObject* obj);
In myclass.cpp source file, I defined a function called SetMyObject() to save the object pointer. This function will later be called in QML.
void MyClass::SetMyObject(QObject* obj)
// Set the object pointer
myObject = obj;
After that, in main.cpp, include MyClass header and register it to QML engine using the function qmlRegisterType():
int main(int argc, char *argv)
// Register your class to QML
qmlRegisterType<MyClass>("MyClassLib", 1, 0, "MyClass");
Notice there are 4 parameters you need to declare in qmlRegisterType(). Besides declaring your class name (i.e. MyClass), you also need to declare your library name (i.e. MyClassLib) and its version (i.e. version 1.0), which will be used for importing your class to QML later on.
Now that QML engine is fully aware of my custom class, I can then map it to my label object in QML. First off, in my QML file, I imported my class library by calling import MyClassLib 1.0. Notice that the library name and its version number have to be matching with the one you declared in main.cpp, otherwise it will throw you an error.
After declaring MyClass in QML (and set its id as myclass), I then call myclass.SetMyObject(myLabel) to expose the label’s pointer to C/C++ right after the label is being initialized:
import MyClassLib 1.0
text: qsTr("Hello World!")
Please be aware that you need to wait until the label is fully initiated before exposing its pointer to C/C++, otherwise you may cause the program to crash. To make sure it’s fully initiated, call SetMyObject() within Component.onCompleted and not other places.
Now that the QML label is being exposed to C/C++, I can do whatever I want to the label. For instance, I can set its visibility to true and change its text to “Bye bye world!”:
// QVariant automatically detects your data type
myObject->setProperty("text", QVariant("Bye bye world!"));
Besides changing the properties, I can also call its functions by calling QMetaObject::invokeMethod():
QVariant message = "Hello world!";
qDebug() << "QML function returned:" << returnedValue.toString();
That’s all for this tutorial. If you have any problem please feel free to leave a comment below. Happy coding!