How to make friends QML with someone else's OpenGL context. Part II: Downloading QML

  • Tutorial
In this article I will try to talk about how to load QML if you, for some reason, have no way to use QQuickView , but you need to work directly with QQuickWindow .
In my case, that of the reason was that with QQuickRenderControl can work only QQuickWindow. In your case, such a reason could be, for example, that you needed to load QML not from any file, but from memory, for example, which opens the possibility of generating QML on the fly, or requesting the contents of QML, or part of it, from the user - funny right?

In case you have not read the beginning: Part I is available at this link .

In fact, in the task, there is almost nothing complicated, just read the documentation carefully or look at the source of QQuickView.

So, about everything, in order

The first thing we need is a QQmlEngine :

    QQmlEngine* qmlEngine = new QQmlEngine;

Next, we need a QQmlComponent - it is with its help that QML is loaded. Its important feature is that depending on the source of QML, QQmlComponent can load it both synchronously and asynchronously.

You can handle this as follows (this is exactly the code used in QQuickView):

    const QUrl source = QStringLiteral( "" );
    qmlComponent = new QQmlComponent( &qmlEngine, source );
    if( qmlComponent->isLoading() )
        connect( qmlComponent, &QQmlComponent::statusChanged, componentStatusChanged );
        componentStatusChanged( qmlComponent->status() );

but personally to me, this implementation is more impressive:

    const QUrl source = QStringLiteral( "" );
    qmlComponent = new QQmlComponent( qmlEngine );
    connect( qmlComponent, &QQmlComponent::statusChanged, componentStatusChanged );
    qmlComponent->loadUrl( source );

Since in this case, synchronous and asynchronous downloads are processed identically (and fewer branches in the code - fewer reasons to make mistakes).

If you need to download QML from QString, the code will look like this:

    const QUrl qmlUrl = QStringLiteral( "" );
    const QString qml = QStringLiteral( "import QtQuick 2.0; Rectangle { color: 'green'; }" );
    qmlComponent = new QQmlComponent( qmlEngine );
    connect( qmlComponent, &QQmlComponent::statusChanged, componentStatusChanged );
    qmlComponent->setData( qml.toUtf8(), qmlUrl );

In this case, although QML is loaded from a string, you can specify the URL with which this QML will be associated. This is necessary if any external elements (links to other QML components or files) are used in the text of the QML string, the search of which will be carried out relative to the transmitted URL.

Well, all that remains for us is to process the download result:

void componentStatusChanged( QQmlComponent::Status status )
    Q_ASSERT( !m_rootItem );
    if( QQmlComponent::Ready != status ) {
    QObject* rootObject = qmlComponent->create();
    QQuickItem* rootItem = qobject_cast( rootObject );
    if( !rootItem ) {
    rootItem->setParentItem( quickWindow->contentItem() );
    rootItem->setSize( QSizeF( quickWindow->width(), quickWindow->height() ) );

Important note: in the above code, both ownership issues and error handling issues are deliberately ignored.

Actually, this was all that was needed to solve the second part of the original problem .

A class implementing the above concept, as usual, is available on GitHub: FboQuickView.h , FboQuickView.cpp
Well, as before, comments, questions, healthy criticism are welcome.

Continued: Part III: User Input Processing

Also popular now: