3

In my application I want to create another window with QML UI from C++ code.

I know it's possible to create another window using QML Window type, but I need the same thing from C++ code.

So far I managed to load my additional qml file into QQmlComponent:

QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(QUrl(QStringLiteral("qrc:/testqml.qml")));
if ( component.isReady() )
    component.create();
else
    qWarning() << component.errorString();

How do I display it in a separate window?

Aleksei Petrenko
  • 6,698
  • 10
  • 53
  • 87

3 Answers3

6

You can achieve that using a single QQmlEngine. Following your code, you could do something like this:

QQmlEngine engine;
QQmlComponent component(&engine);
component.loadUrl(QUrl(QStringLiteral("qrc:/main.qml")));

if ( component.isReady() )
    component.create();
else
    qWarning() << component.errorString();

component.loadUrl(QUrl(QStringLiteral("qrc:/main2.qml")));

if ( component.isReady() )
    component.create();
else
    qWarning() << component.errorString();

I prefer QQmlApplicationEngine though. This class combines a QQmlEngine and QQmlComponent to provide a convenient way to load a single QML file. So you would have fewer lines of codes if you have the opportunity of using QQmlApplicationEngine.

Example:

QGuiApplication app(argc, argv);

QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
engine.load(QUrl(QStringLiteral("qrc:/main2.qml")));

return app.exec();

We could also use QQuickView. QQuickView only supports loading of root objects that derive from QQuickItem so in this case our qml files couldn't start with the QML types ApplicationWindow or Window like in the examples above. So in this case, our main could be something like this:

QGuiApplication app(argc, argv);

QQuickView view;
view.setSource(QUrl("qrc:/main.qml"));
view.show();

QQuickView view2;
view2.setSource(QUrl("qrc:/main2.qml"));
view2.show();

return app.exec();
Tarod
  • 6,732
  • 5
  • 44
  • 50
  • 1
    Thanks for your answer. So, I assume the second solution will work if I use "Window" or "ApplicationWindow" QML type as a root element of my QML. Am I correct? I guess this is the thing I haven't realized - I thought I should create window from C++ somehow. Now I understand that QML rules it all. – Aleksei Petrenko Feb 01 '16 at 14:49
  • You're right :) `QQmlApplicationEngine` does not automatically create a root window. After reading your message, I think it's a good idea to update my answer with another option: using `QQuickView`. In this case, as you know, `QQuickView` only supports loading of root objects that derive from `QQuickItem`. – Tarod Feb 02 '16 at 08:05
  • 1
    For some reason your solution with one QQmlApplicationEngine and two loaded files didn't work for me, the second window just refused to show up. Maybe it was some bug in my code. Anyway, I've found a better way to solve this problem (in my case), posted it as another answer. Thank you for your help anyway! – Aleksei Petrenko Feb 03 '16 at 07:58
  • I am sorry to hear that :( In case you want to see the code working or just to play with it, I've uploaded the code to GitHub. Anyway, I saw your new answer and it's great! :) – Tarod Feb 03 '16 at 09:01
1

You can try to create new QQmlEngine

0

For anyone curious, I ended up solving the problem with slightly different approach.

My root QML document now looks like this:

import QtQuick 2.4

Item {
    MyMainWindow {
        visible: true
    }

    MyAuxiliaryWindow {
        visible: true
    }
}

Where MainWindow is a QML component with root element ApplicationWindow and AuxiliaryWindow is a component with root element Window.

Works just fine and you don't have to worry about loading two separate QML files.

Aleksei Petrenko
  • 6,698
  • 10
  • 53
  • 87