В моем случае, таковой причиной являлось то, что с QQuickRenderControl умеет работать только QQuickWindow. В вашем же случае, таковой причиной может быть например то, что вам понадобилось загружать QML не из какого либо файла, а например из памяти, что открывает возможность генерации QML «на лету», или запроса содержимого QML, или его части, у пользователя — занятно, не так ли?
На случай если вы не читали начало: Часть I доступна по данной ссылке.
На самом деле, в поставленной задаче, нет практически ничего сложного, достаточно внимательно почитать документацию или же заглянуть в исходники QQuickView.
Итак, обо всем, по порядку
Первое что нам потребуется, это QQmlEngine:
QQmlEngine* qmlEngine = new QQmlEngine;
Далее нам нужен QQmlComponent — именно с его помощью осуществляется загрузка QML. Важной его особенностью является то что в зависимости от источника QML, QQmlComponent может грузить его как синхронно, так и асинхронно.
Обработать это можно следующим образом (именно такой код используется в QQuickView):
const QUrl source = QStringLiteral( "http://example.com/main.qml" ); qmlComponent = new QQmlComponent( &qmlEngine, source ); if( qmlComponent->isLoading() ) connect( qmlComponent, &QQmlComponent::statusChanged, componentStatusChanged ); else componentStatusChanged( qmlComponent->status() );
но лично мне, больше импонирует такая реализация:
const QUrl source = QStringLiteral( "http://example.com/main.qml" ); qmlComponent = new QQmlComponent( qmlEngine ); connect( qmlComponent, &QQmlComponent::statusChanged, componentStatusChanged ); qmlComponent->loadUrl( source );
Поскольку в этом случае синхронная и асинхронная загрузки обрабатываются идентично (а меньше ветвлений в коде — меньше поводов ошибиться).
В случае необходимости загрузки QML из QString, код будет выглядеть следующим образом:
const QUrl qmlUrl = QStringLiteral( "http://example.com/main.qml" ); 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 );
В данном случае, несмотря на то что QML загружается из строки, можно указать URL с которым данный QML будет ассоциирован. Это необходимо в том случае, если в тексте QML строки используются какие либо внешние элементы (ссылки на другие QML компоненты или файлы), поиск которых и будет осуществляться относительно переданного URL.
Ну а нам осталось только обработать результат загрузки:
void componentStatusChanged( QQmlComponent::Status status ) { Q_ASSERT( !m_rootItem ); if( QQmlComponent::Ready != status ) { return; } QObject* rootObject = qmlComponent->create(); QQuickItem* rootItem = qobject_cast<QQuickItem*>( rootObject ); if( !rootItem ) { return; } rootItem->setParentItem( quickWindow->contentItem() ); rootItem->setSize( QSizeF( quickWindow->width(), quickWindow->height() ) ); }
Важное замечание: в вышеприведенном коде, сознательно абсолютно проигнорированы как вопросы владения объектами, так и вопросы обработки ошибок.
Собственно это было все что было необходимо для решения второй части исходной задачи.
Класс реализующий вышеприведенную концепцию, как обычно, доступен на GitHub: FboQuickView.h, FboQuickView.cpp
Ну и как и прежде, коментарии, вопросы, здоровая критика — приветствуются.
Продолжение следует…
ссылка на оригинал статьи http://habrahabr.ru/post/248103/
Добавить комментарий