我正在通过以下代码创建一个新窗口:

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();
这段代码为rootContext设置了 MyController 属性,这意味着根上下文中的所有页面都可以访问此属性。因此,这将不允许我从同一QML文件打开2个不同的窗口,每个窗口都有其自己的MainController实例。
问题:如何将此 MyController的属性绑定(bind)到QQuickWindow上下文而不是引擎的rootContext?
我尝试使用QQuickView并执行以下操作:
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();
但是我收到以下消息:

最佳答案

QQuickWindow不拥有自己的任何上下文属性,因此无法使用它来设置上下文属性。

就像消息中所解释的一样,QQuickView需要一个从QQuickItem继承的QML根对象,这意味着根可以是RectangleItem等,但不能是ApplicationWindowWindow,因为它们不是从QQuickItem继承的。如果您可以将根对象更改为Rectangle之类的内容,则可以创建QQuickView的不同实例以实现您的目标,因为如果不向其提供现有的QQuickView,则每个QQmlEngine都会创建自己的QQmlEngine
QQmlApplicationEngine实际上是从QQmlEngine继承的,因此每个实例都有其自己的根上下文。例如,两次调用以下createMain()将创建两个带有单独的引擎,单独的 Controller 和单独的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();
}

如果您不满意创建QQmlAppicationEngine的多个拷贝,则可以共享一个QQmlApplicationEngine实例,并为每个窗口实例创建一个子上下文:
// 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();
}

当然,如果不使用QQmlApplicationEngine的功能,则可以将QQmlApplication更改为QQmlEngine

10-07 22:03
查看更多