QML is designed to be easily extensible toand from C++. The classes in the Qt Declarative module allow QML components tobe loaded and manipulated from C++, and through Qt's meta-object system,QML and C++ objects can easily communicate through Qt signals and slots. Inaddition, QML plugins can be written to create reusable QML components fordistribution.
You may want to mix QML and C++ for anumber of reasons. For example:
· To use functionality defined in a C++source (for example, when using a C++ Qt-based data model, or calling functionsin a third-party C++ library)
· To access functionality in the QtDeclarative module (for example, to dynamically generate images usingQDeclarativeImageProvider)
· To write your own QML elements (whether foryour applications, or for distribution to others)
To use the Qt Declarative module, you mustinclude and link to the module appropriately, as shown on the module index page.The Qt Declarative UI Runtime documentation shows howto build a basic C++ application that uses this module.
Core module classes
The Qt Declarative module provides a set ofC++ APIs for extending your QML applications from C++ and embedding QML intoC++ applications. There are several core classes in the Qt Declarative modulethat provide the essential capabilities for doing this. These are:
· QDeclarativeEngine:A QML engine provides the environment for executing QML code. Every applicationrequires at least one engine instance.
· QDeclarativeContext:A context allows an application to expose data to the QML components created byan engine.
A QDeclarativeEngine allows the configurationof global settings that apply to all of its QML component instances: forexample, the QNetworkAccessManager to be used for networkcommunications, and the file path to be used for persistent storage.
QDeclarativeComponent is used to load QML documents.Each QDeclarativeComponent instance represents asingle document. A component can be created from the URL or file path of a QMLdocument, or the raw QML code of the document. Component instances areinstatiated through theQDeclarativeComponent::create()method, like this:
QML documents can also be loaded using QDeclarativeView.This class provides a convenient QWidget-based viewfor embedding QML components into QGraphicsView-basedapplications. (For other methods of integrating QML into QWidget-basedapplications, see Integrating QML Code withexisting Qt UI code.)
Approaches to using QML with C++
There are a number of ways to extend yourQML application through C++. For example, you could:
· Load a QML component and manipulate it (orits children) from C++
· Embed a C++ object and its propertiesdirectly into a QML component (for example, to make a particular C++ objectcallable from QML, or to replace a dummy list model with a real data set)
· Define new QML elements (through QObject-based C++classes) and create them directly from your QML code
These methods are shown below. Naturallythese approaches are not exclusive; you can mix any of these methods throughoutyour application as appropriate.
Loading QML componentsfrom C++
A QML document can be loaded with QDeclarativeComponent or QDeclarativeView. QDeclarativeComponentloadsa QML component as a C++ object; QDeclarativeView also does this, butadditionally loads the QML component directly into a QGraphicsView. It isconvenient for loading a displayable QML component into a QWidget-basedapplication.
For example, suppose there is a MyItem.qml file that looks likethis:
This QML document can be loaded with QDeclarativeComponent or QDeclarativeView with the following C++code. Using a QDeclarativeComponent requires calling QDeclarativeComponent::create()to create a new instance of the component, while a QDeclarativeView automatically creates aninstance of the component, which is accessible via QDeclarativeView::rootObject():
1. // Using QDeclarativeView
2. QDeclarativeView view;
5. QObject *object = view.rootObject();
Alternatively, you can cast the object toits actual type and call functions with compile-time safety. In this case thebase object of MyItem.qml is an Item, which isdefined by theQDeclarativeItem class:
Locating child objects
QML components are essentially object treeswith children that have siblings and their own children. Child objects of QMLcomponents can be located using the QObject::objectName property withQObject::findChild().For example, if the root item in MyItem.qml had a child Rectangle item:
The child could be located like this:
If objectName is used inside a delegateof a ListView, Repeater or some other elementthat creates multiple instances of its delegates, there will be multiplechildren with the same objectName. In this case, QObject::findChildren()can be used to find all children with a matching objectName.
Warning: While it is possible touse C++ to access and manipulate QML objects deep into the object tree, werecommend that you do not take this approach outside of application testing andprototyping. One strength of QML and C++ integration is the ability toimplement the QML user interface separately from the C++ logic and datasetbackend, and this strategy breaks if the C++ side reaches deep into the QMLcomponents to manipulate them directly. This would make it difficult to, forexample, swap a QML view component for another view, if the new component wasmissing a required objectName. It is better for theC++ implementation to know as little as possible about the QML user interfaceimplementation and the composition of the QML object tree.
Embedding C++ objectsinto QML components
When loading a QML scene into a C++application, it can be useful to directly embed C++ data into the QML object. QDeclarativeContext enables this by exposingdata to the context of a QML component, allowing data to be injected from C++into QML.
For example, here is a QML item that refersto a currentDateTime value that does not existin the current scope:
This currentDateTime value can be set directlyby the C++ application that loads the QML component, using QDeclarativeContext::setContextProperty():
Context properties can hold either QVariant or QObject* values.This means custom C++ objects can also be injected using this approach, andthese objects can be modified and read directly in QML. Here, we modify theabove example to embed a QObject instance instead of a QDateTime value, and the QML codeinvokes a method on the object instance:
(Note that date/time values returned fromC++ to QML can be formatted through Qt.formatDateTime() and associatedfunctions.)
If the QML item needs to receive signalsfrom the context property, it can connect to them using theConnections element. For example, if ApplicationData has a signal named dataChanged(), this signal can beconnected to using an onDataChanged handler within a Connections object:
Context properties can be useful for usingC++ based data models in a QML view. See the String ListModel, Object ListModel and AbstractItemModel models for respectiveexamples on usingQStringListModel, QObjectList-basedmodels and QAbstractItemModel in QML views.
Also see the QDeclarativeContext documentation for moreinformation.
Defining new QML elements
While new QML elements can be defined in QML, theycan also be defined by C++ classes; in fact, many of the core QML Elements are implemented throughC++ classes. When you create a QML object using one of these elements, you aresimply creating an instance of a QObject-based C++class and setting its properties.
To create a visual item that fits in withthe Qt Quick elements, base your class off QDeclarativeIteminsteadof QObject directly. You can thenimplement your own painting and functionality like any other QGraphicsObject.Note that QGraphicsItem::ItemHasNoContents is set by default onQDeclarativeItem because it does not paintanything; you will need to clear this if your item is supposed to paintanything (as opposed to being solely for input handling or logical grouping).
For example, here is an ImageViewer class with an image URL property:
Then, any QML code loaded by your C++application or plugin can create and manipulate ImageViewerobjects:
It is advised that you avoid using QGraphicsItem functionality beyond theproperties documented inQDeclarativeItem.This is because the GraphicsView backend is intended to bean implementation detail for QML, so the QtQuick items can be moved to fasterbackends as they become available with no change from a QML perspective. Tominimize any porting requirements for custom visual items, try to stick to thedocumented properties in QDeclarativeItem where possible.Properties QDeclarativeItem inherits but doesn'tdocument are classed as implementation details; they are not officiallysupported and may disappear between releases.