Viadeo Twitter Google Bookmarks ! Facebook Digg del.icio.us MySpace Yahoo MyWeb Blinklist Netvouz Reddit Simpy StumbleUpon Bookmarks Windows Live Favorites 
Logo Documentation Qt ·  Page d'accueil  ·  Toutes les classes  ·  Classes principales  ·  Annotées  ·  Classes groupées  ·  Modules  ·  Fonctions  · 

The QML Engine

The QML engine runs and executes QML applications. The engine loads, instantiates, and executes the QML context as specified in QML files, plugins, or applications.

Core Module Classes

The Qt Declarative module provides a set of C++ APIs for extending your QML applications from C++ and embedding QML into C++ applications. There are several core classes in the Qt Declarative module that provide the essential capabilities for doing this. These are:

  • QQmlEngine: A QML engine provides the environment for executing QML code. Every application requires at least one engine instance.
  • QQmlComponent: A component encapsulates QML information.
  • QQmlContext: A context allows an application to expose data to the QML components created by an engine.

The Qt Declarative module consists of the engine, context, component encapsulation, and visual items.

Declarative Engine

A QQmlEngine allows the configuration of global settings that apply to all of its QML component instances: for example, the QNetworkAccessManager to be used for network communications, and the file path to be used for persistent storage.

QQmlComponent is used to load QML documents. Each QQmlComponent instance represents a single document. A component can be created from the URL or file path of a QML document, or the raw QML code of the document. Component instances are instatiated through the QQmlComponent::create() method, like this:

 QQmlEngine engine;
 QQmlComponent component(&engine, QUrl::fromLocalFile("MyRectangle.qml"));
 QObject *rectangleInstance = component.create();

 // ...
 delete rectangleInstance;

QML documents can also be loaded using QQuickView. This class provides a convenient QWidget-based view for embedding QML components into QGraphicsView-based applications. (For other methods of integrating QML into QWidget-based applications, see Integrating QML Code with existing Qt UI code.)

Engine and Context Initialization

Loading QML Components from C++

A QML document can be loaded with QQmlComponent or QQuickView. QQmlComponent loads a QML component as a C++ object; QQuickView also does this, but additionally loads the QML component directly into a QGraphicsView. It is convenient for loading a displayable QML component into a QWidget-based application.

For example, suppose there is a MyItem.qml file that looks like this:


This QML document can be loaded with QQmlComponent or QQuickView with the following C++ code. Using a QQmlComponent requires calling QQmlComponent::create() to create a new instance of the component, while a QQuickView automatically creates an instance of the component, which is accessible via QQuickView::rootObject():

 ...

This object is the instance of the MyItem.qml component that has been created. You can now modify the item's properties using QObject::setProperty() or QQmlProperty:


Alternatively, you can cast the object to its actual type and call functions with compile-time safety. In this case the base object of MyItem.qml is an Item, which is defined by the QQuickItem class:


You can also connect to any signals or call functions defined in the component using QMetaObject::invokeMethod() and QObject::connect(). See Exchanging data between QML and C++ below for further details.

Locating child objects

QML components are essentially object trees with children that have siblings and their own children. Child objects of QML components can be located using the QObject::objectName property with QObject::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 delegate of a ListView, Repeater or some other element that creates multiple instances of its delegates, there will be multiple children 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 to use C++ to access and manipulate QML objects deep into the object tree, we recommend that you do not take this approach outside of application testing and prototyping. One strength of QML and C++ integration is the ability to implement the QML user interface separately from the C++ logic and dataset backend, and this strategy breaks if the C++ side reaches deep into the QML components to manipulate them directly. This would make it difficult to, for example, swap a QML view component for another view, if the new component was missing a required objectName. It is better for the C++ implementation to know as little as possible about the QML user interface implementation and the composition of the QML object tree.

Embedding C++ Objects into QML Components

When loading a QML scene into a C++ application, it can be useful to directly embed C++ data into the QML object. QQmlContext enables this by exposing data to the context of a QML component, allowing data to be injected from C++ into QML.

For example, here is a QML item that refers to a currentDateTime value that does not exist in the current scope:


This currentDateTime value can be set directly by the C++ application that loads the QML component, using QQmlContext::setContextProperty():


Context properties can hold either QVariant or QObject* values. This means custom C++ objects can also be injected using this approach, and these objects can be modified and read directly in QML. Here, we modify the above example to embed a QObject instance instead of a QDateTime value, and the QML code invokes a method on the object instance:



(Note that date/time values returned from C++ to QML can be formatted through Qt.formatDateTime() and associated functions.)

If the QML item needs to receive signals from the context property, it can connect to them using the Connections element. For example, if ApplicationData has a signal named dataChanged(), this signal can be connected to using an onDataChanged handler within a Connections object:


Context properties can be useful for using C++ based data models in a QML view. See the String ListModel, Object ListModel and AbstractItemModel models for respective examples on using QStringListModel, QObjectList-based models and QAbstractItemModel in QML views.

Also see the QQmlContext documentation for more information.

Invoking QML Entities through the Engine

QML and C++ objects can communicate with one another through signals, slots and property modifications. For a C++ object, any data that is exposed to Qt's Meta-Object System that is, properties, signals, slots and Q_INVOKABLE methods - become available to QML. On the QML side, all QML object data is automatically made available to the meta-object system and can be accessed from C++.

The C++ Types as QML Types article covers the topic of exposing Qt functions and properties to the declarative engine.

Calling Functions

QML functions can be called from C++ and vice-versa.

All QML functions are exposed to the meta-object system and can be called using QMetaObject::invokeMethod(). Here is a C++ application that uses this to call a QML function:



Notice the Q_RETURN_ARG() and Q_ARG() arguments for QMetaObject::invokeMethod() must be specified as QVariant types, as this is the generic data type used for QML functions and return values.

To call a C++ function from QML, the function must be either a Qt slot, or a function marked with the Q_INVOKABLE macro, to be available to QML. In the following example, the QML code invokes methods on the myObject object, which has been set using QQmlContext::setContextProperty():



QML supports the calling of overloaded C++ functions. If there are multiple C++ functions with the same name but different arguments, the correct function will be called according to the number and the types of arguments that are provided.

Receiving Signals

All QML signals are automatically available to C++, and can be connected to using QObject::connect() like any ordinary Qt C++ signal. In return, any C++ signal can be received by a QML object using signal handlers.

Here is a QML component with a signal named qmlSignal. This signal is connected to a C++ object's slot using QObject::connect(), so that the cppSlot() method is called whenever the qmlSignal is emitted:



To connect to Qt C++ signals from within QML, use a signal handler with the on<SignalName> syntax. If the C++ object is directly creatable from within QML (see Defining new QML elements above) then the signal handler can be defined within the object declaration. In the following example, the QML code creates a ImageViewer object, and the imageChanged and loadingError signals of the C++ object are connected to through onImagedChanged and onLoadingError signal handlers in QML:

     ...

(Note that if a signal has been declared as the NOTIFY signal for a property, QML allows it to be received with an on<Property>Changed handler even if the signal's name does not follow the <Property>Changed naming convention. In the above example, if the "imageChanged" signal was named "imageModified" instead, the onImageChanged signal handler would still be called.)

If, however, the object with the signal is not created from within the QML code, and the QML item only has a reference to the created object - for example, if the object was set using QQmlContext::setContextProperty() - then the Connections element can be used instead to create the signal handler:



C++ signals can use enum values as parameters provided that the enum is declared in the class that is emitting the signal, and that the enum is registered using Q_ENUMS. See Using enumerations of a custom type below for details.

Modifying Properties

Any properties declared in a QML object are automatically accessible from C++. Given a QML item like this:


The value of the someNumber property can be set and read using QQmlProperty, or QObject::setProperty() and QObject::property():


You should always use QObject::setProperty(), QQmlProperty or QMetaProperty::write() to change a QML property value, to ensure the QML engine is made aware of the property change. For example, say you have a custom element PushButton with a buttonText property that internally reflects the value of a m_buttonText member variable. Modifying the member variable directly like this is not a good idea:

 // BAD!
 QQmlComponent component(engine, "MyButton.qml");
 PushButton *button = qobject_cast<PushButton*>(component.create());
 button->m_buttonText = "Click me";

Since the value is changed directly, this bypasses Qt's meta-object system and the QML engine is not made aware of the property change. This means property bindings to buttonText would not be updated, and any onButtonTextChanged handlers would not be called.

Any Qt properties - that is, those declared with the Q_PROPERTY() macro - are accessible from QML. Here is a modified version of the earlier example on this page; here, the ApplicationData class has a backgroundColor property. This property can be written to and read from QML:



Notice the backgroundColorChanged signal is declared as the NOTIFY signal for the backgroundColor property. If a Qt property does not have an associated NOTIFY signal, the property cannot be used for Property Binding in QML, as the QML engine would not be notified when the value changes. If you are using custom types in QML, make sure their properties have NOTIFY signals so that they can be used in property bindings.

The C++ Types as QML Types article covers the topic of exposing Qt properties to the runtime. For more information, the Writing QML extensions with C++ tutorial demonstrates basic usage patterns.

Loading QML Plugins

Additional Qt code is runnable in the engine as a QML plugin. The QML Plugins article covers the creation and usage patterns of QML plugins. The QQmlExtensionPlugin class is an abstract class for writing QML plugins. The How to Create Qt Plugins contains more information about Qt's plugin system.

Optimization

Often, to develop high performance elements it is helpful to know more about the status of the QML engine. For example, it might be beneficial to delay initializing some costly data structures until after all the properties have been set.

The QML engine defines an interface class called QQmlParserStatus, which contains a number of virtual methods that are invoked at various stages during component instantiation. To receive these notifications, an element implementation inherits QQmlParserStatus and notifies the Qt meta system using the Q_INTERFACES() macro.

 class Example : public QObject, public QQmlParserStatus
 {
     Q_OBJECT
     Q_INTERFACES(QQmlParserStatus)
 public:
     virtual void componentComplete()
     {
         qDebug() << "Woohoo!  Now to do my costly initialization";
     }
 };

Memory Management and QVariant types

It is a component's responsibility to ensure that it does not access or return pointers to invalid objects. QML makes the following guarentees:

  • An object assigned to a QObject (or QObject-derived) pointer property will be valid at the time of assignment.

    Following assignment, it is the responsibility of the class to subsequently guard this pointer, either through a class specific method or the generic QPointer class.

  • An object assigned to a QVariant will be valid at the time of assignment.

    When assigning an object to a QVariant property, QML will always use a QMetaType::QObjectStar typed QVariant. It is the responsibility of the class to guard the pointer. A general rule when writing a class that uses QVariant properties is to check the type of the QVariant when it is set and if the type is not handled by your class, reset it to an invalid variant.

  • An object assigned to a QObject (or QObject-derived) list property will be valid at the time of assignment.

    Following assignment, it is the responsibility of the class to subsequently guard this pointer, either through a class specific method or the generic QPointer class.

Components should assume that any QML assigned object can be deleted at any time, and respond accordingly. If documented as such an element need not continue to work in this situation, but it must not crash.

JavaScript Runtime

The runtime implements the ECMAScript Language Specification standard, 5th edition. The reserved words, conditionals, variables, and object behaviors follow after the standard.

The QML JavaScript Host Environment article has information about the JavaScript host environment provided by QML, which is different than the browser host environment many are familiar with.

The JavaScript Code article has information about placing JavaScript code within QML code.

Cette page est une traduction d'une page de la documentation de Qt, écrite par Nokia Corporation and/or its subsidiary(-ies). Les éventuels problèmes résultant d'une mauvaise traduction ne sont pas imputables à Nokia. Qt 5.0-snapshot
Copyright © 2012 Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon, vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E de dommages et intérêts. Cette page est déposée à la SACD.
Vous avez déniché une erreur ? Un bug ? Une redirection cassée ? Ou tout autre problème, quel qu'il soit ? Ou bien vous désirez participer à ce projet de traduction ? N'hésitez pas à nous contacter ou par MP !
 
 
 
 
Partenaires

Hébergement Web