I am creating a new window through the following code:
QMainController* myController = new QMainController(0,m_autenticado);
QQmlApplicationEngine* engine = new QQmlApplicationEngine(this);
engine->rootContext()->setContextProperty("MyController", myController);
engine->load(QUrl(QStringLiteral("qrc:///newPage.qml")));
QQuickWindow* window = qobject_cast<QQuickWindow*>(engine->rootObjects().at(0));
window->showFullScreen();
This code sets a MyController property to the rootContext, which means that all the pages at the root context will have access to this property. And so, this won't allow me to open 2 different windows from the same QML file, each with its own instance of MainController.
QUESTION: How can I bind this MyController property to the QQuickWindow context instead of the engine's rootContext?
I've tried to use a QQuickView and doing like this:
QMainController* myController = new QMainController(0,m_autenticado);
QQuickView* view = new QQuickView();
view->rootContext()->setContextProperty("MyController", myController );
view->setSource(QUrl(QStringLiteral("qrc:///main.qml")));
view->showFullScreen();
But I was complained with the following message:
"QQuickView only supports loading of root objects that derive from QQuickItem.
If your example is using QML 2, (such as qmlscene) and the .qml file you loaded has 'import QtQuick 1.0' or 'import Qt 4.7', this error will occur.
To load files with 'import QtQuick 1.0' or 'import Qt 4.7', use the QDeclarativeView class in the Qt Quick 1 module."
QQuickWindow
does not own any context property of its own so there is no way to set context property with it.
Just like the message explains, QQuickView
expects a QML root object that is inherited from QQuickItem
, which means the root can be a Rectangle
, Item
etc, but not ApplicationWindow
or Window
, since they are not inherited from QQuickItem
. If you can change root object to something like Rectangle
, you can create different instances of QQuickView
to reach your goal, since each QQuickView
creates its own QQmlEngine
if you don't provide an existing QQmlEngine
to it.
QQmlApplicationEngine
actually inherits from QQmlEngine
, so each instance has its own root context. For example calling the following createMain()
twice will create two windows with separate engines, separate controller and separate rootContext:
void foo::createMain() {
//TODO: Set a proper parent to myController
QMainController* myController = new QMainController(0,m_autenticado);
QQmlApplicationEngine* engine = new QQmlApplicationEngine(this);
engine->rootContext()->setContextProperty("MyController", myController);
engine->load(QUrl(QStringLiteral("qrc:///newPage.qml")));
QQuickWindow* window = qobject_cast<QQuickWindow*>(engine->rootObjects().at(0));
window->showFullScreen();
}
If you don't feel right about creating multiple copies of QQmlAppicationEngine
, you can share one instance of QQmlApplicationEngine
instead, and create a child context for each window instance:
// foo.h
class foo {
private:
QQmlApplicationEngine m_engine; // can change to QQmlEngine if you prefer
}
// foo.cpp
void foo::createMain()
{
//TODO: Set a proper parent to myController
QMainController* myController = new QMainController(0,m_autenticado);
// Create a new context as a child of m_engine.rootContext()
QQmlContext *childContext = new QQmlContext(&m_engine, &m_engine);
childContext->setContextProperty("MyController", myController);
QQmlComponent *component = new QQmlComponent(&m_engine, &m_engine);
component->loadUrl(QUrl("qrc:///qml/newPage.qml"));
// Create component in child context
QObject *o = component->create(childContext);
QQuickWindow* window = qobject_cast<QQuickWindow*>(o);
window->show();
}
And of course you can change QQmlApplication
to QQmlEngine
if there's no use of QQmlApplicationEngine's features.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With