DataSharingQML2CPP

From Qt Wiki
Jump to: navigation, search
This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

Sharing Data Between QML Documents and C++ Objects

Qt Quick is now officially released with Qt 4.7. Here's a look at available techniques for sharing data between QML documents and C++ objects. In general, exposing a QObject will make all of its signals, slots and properties available to the QML environment.

Sharing values

All QML code executes within a context. The context keeps track of what data is available to different leaves and nodes in a QML object tree. Data is shared as context properties or context objects. A context property is simply a way to expose a given QObject through a given name. For example, to expose a QColor property named frameColor to QML, simply use the following snippet:

QDeclarativeContext *context = ;
context->setContextProperty("frameColor", QColor(Qt::red));

This property can then be accessed from within the QML context as a global property, as shown below. Remember property values are bound, not assigned, in QML. This means you can alter the frameColor property from C++ and the change will be reflected in QML.

Rectangle {
 border.color: frameColor
}

It is possible to add multiple context properties to a QDeclarativeContext object, but as the list of properties climbs the readability of the code crumbles. Instead of setting each property individually, it is cleaner to gather all context properties into one QObject and set the single object as the context object instead.

The next snippet defines the interface object MyInterface using the setContextProperty method. The Q_PROPERTY macro defines the properties available within MyInterface to the Qt property system and sets notification signals, allowing subsequent bindings to work.

Note that all properties added explicitly by QDeclarativeContext::setContextProperty() [doc.qt.nokia.com] take precedence over the context object’s default properties.

class MyInterface :  {
 
 Q_PROPERTY(QAbstractItemModel *myModel READ model NOTIFY modelChanged)
 
 };

MyInterface *myInterface = new MyInterface;
 QDeclarativeEngine engine;
 QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
 context->setContextObject(myInterface);

QDeclarativeComponent component(&engine, "ListView { model=myModel }");
 component.create(context);

QML views into C++ models

Object properties work well when providing a limited set of values to QML, but are difficult to manage when large data sets are involved. In these cases formal models are visualized with formal views.

Qt widgets can create views into models that are exposed using the QAbstractItemModel interface. This interface is also supported by QML.

To expose a QAbstractItemModel to QML a context property is used:

QAbstractItemModel *model = ;
context->setContextProperty("dataModel", model);

QML currently provides three elements devoted to creating views into models. The ListView and GridView elements create list and grid views respectively. The PathView element lays out model-provided items on a path, for example a loop path that allows you to create a carousel interface into a list.

Regardless of the view element employed, the context property set to the data model is bound to the model property of a view element.

ListView {
 model: contactModel
 delegate: delegate
 highlight: highlight
}

The actual visualization of each item of the model is handled through components. The highlight and delegate components are instantiated and can use model data when binding properties. The names used to refer to the different roles of the model are set using the QAbstractItemModel::setRoleNames method, which will make them accessible to QML.

Component {
 id: delegate

Item {
 width: 100; height: 40

Row {
 x: 5; y: 5; spacing: 5

Rectangle {
 width: 30; height: 30
 border.width: 2; border.color: "black"
 color: decoration
 }
 Text {
 x: 5; y: 10
 text: display
 }
 }
 }
}

Build models in QML

You can also build models directly in QML using ListModel or XMLListModel. For example, let’s use ListModel and PathView to the a view like the following rotating carousel. (see also the PathView documentation.)

http://doc.trolltech.com/4.7-snapshot/images/pathview.gif(Carousel view) (Carousel view)

Start by creating a list model:

 import Qt 4.7

ListModel {
 ListElement {
 name: "Bill Jones"
 icon: "pics/qtlogo.png"
 }
 ListElement {
 name: "Jane Doe"
 icon: "pics/qtlogo.png"
 }
 ListElement {
 name: "John Smith"
 icon: "pics/qtlogo.png"
 }
 }

Save the model in the file ContactModel.qml and represent it as rotating carousel using:

 import Qt 4.7

Rectangle {
 width: 240; height: 200

Component {
 id: delegateItem
 Column {
 Image { anchors.horizontalCenter:
 name.horizontalCenter;
 width: 64; height: 64;
 source: icon
 }
 Text { text: name; font.pointSize: 16 }
 }
 }

PathView {
 anchors.fill: parent
 model: ContactModel {}
 delegate: delegateItem
 path: Path {
 startX: 120; startY: 100
 PathQuad { x: 120; y: 25; controlX: 260; controlY: 75 }
 PathQuad { x: 120; y: 100; controlX: 20; controlY: 75 }
 }
 }
 }