[QML+Qt CPP] How to move from Screen-to-Screen in an application?
-
Greetings!
I'm trying to make a music player application using QML for front end (GUI) & Qt C++ for the logic.
Issue:-
I have no idea, how should I switch between two or more screens in my application while preserving the state of each screen. I'll explain it more in detail. Imagine I have 4 Screens. Home, Album View, Artist View & Songs View. Now, I'll goto Album View Screen from Home Screen, I'll open an album & see what songs are available. Then from there I'll goto Home again before going to Artist View. I'll see an artists songs then move to Home Screen. Now if you observe, Both Artist & Album view screens are in some state by opening some Artist/Albums Songs. I want to preserve that state, So that when I come back to Album View from Home Screen, I should see that opened state of an Album rather than the default Album/Artist view screen. This is one issue.
Presently, I'm using following code for starting Home Screen. @viewer.setMainQmlFile(QStringLiteral("qml/MediaMock/Screen.qml"));
viewer.setResizeMode(QQuickView::SizeRootObjectToView);
viewer.showFullScreen();@ -
Now the other hurdle: I 'm using following code to get the root object to fill the contents in qml file for viewing from cpp. So, Like this, I have to access the root object from each screen [Home, Albums/Artists Screen etc] so that I have to fill in the data from c++. For example, in Albums Screen, I have to fill in the albums from the list to the grid view in that qml file. I have to do that from cpp (keep all the logic in cpp only). I have to do such things on all screens. So, I should be able to get that root object, by knowing which screen is active and what is the root object etc.
Now, I'm very much confused how to achieve my requirement for loading diff qml files while preserving the states and switching them back & forth. Meanwhile I want the content to be dynamic as i'll be interacting with the screens (where content will be driven from cpp).
@QQuickItem* root = viewer.rootObject();
QQuickItem* ob = root->findChild<QQuickItem *>("statusText");
ob->setProperty("text", "Written from c++"); @
Can someone please help me with this issue. Sorry If I asked a basic question.
Please ask If I am not clear at any point.
Regards,
inblueswithu -
-
I usually take a very different approach than yours:
http://qt-project.org/doc/qt-5.0/qtqml/qtqml-cppintegration-exposecppattributes.html
I keep all my data/logic in C++, but I expose properties and functions to QML via Q_PROPERTY and slots.
Maybe worth a look.
-
Thankyou. :)
Let me check that. On a quick glance of that page it completely deals with how to handle data & signals b/w QML & CPP. Thats good.But what is the solution for my screens :(
-
Well, what I would do is to expose the "state" of each screen. Each QML screen that take reads the state and do what they need to do :)
-
Can you just show some sample code so that I can understand. I tried seeing
states
property in QML but could not find a way. It largely speaks about property changes and change in positioning etc. But I could not find changing b/w completely different screens.
[quote author="t3685" date="1379618855"]Well, what I would do is to expose the "state" of each screen. Each QML screen that take reads the state and do what they need to do :)[/quote] -
I am not talking about using QML states. But rather, your C++ could for example remember what the last artists was that was selected and expose that as property.
When the approriate QML screen is loaded, it will ask the C++ for last selected artists and show the appropriate content. -
I understand what you said. But I don't think my implementation (not yet done, in abstract stage) is going to be capable that way.
At this stage leave the state of that screen (for making work easy). At least I should know how to switch b/w the screens. -
@t3685: After reading the article you "said":http://qt-project.org/doc/qt-5.0/qtqml/qtqml-cppintegration-exposecppattributes.html. I understood how we can expose properties into QML. This method is really useful when we want to create custom types into QML by registering with QML type system. Thank you for showing such a good article.
But here my requirement is quite simple. I just want to fill in data into QML elements (like Text, List, Grid etc). This would be easy by just getting the object from the QML file & setting them accordingly. Both ways (one you said & the one i'm using) have to handle the objects for each of Text/List/Image/Grid etc from C++. So, I would consider the method I'm using now is easy. Because, I need not have to create classes for each of these (Grouped Texts/List/Grid etc) again (which is a hectic job) and make them available in context, from there qml will use them directly.
Am I missing something??
Coming back to my question.. Any ideas?
-
You just need to create one C++ class for each screen. You don't need to create a class for each element. Play around and see what you find is easiest. I don't have experience using your way, so if you want to continue like that you'll have to be creative :)
-
-
Use StackView of Qt Quick Controls
-
I'm using differen approach for starting qml file:
@ QQmlApplicationEngine *engine = new QQmlApplicationEngine;if (!engine) {
qDebug() << "Error creating QQmlApplicationEngine";
return 1;
}
QQmlContext *context = engine->rootContext();
context->setContextProperty("settings", &settings);engine->load(QUrl("qml/Program/main.qml"));
QObject *topLevel = engine->rootObjects().value(0);
QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
if ( !window ) {
qWarning("Error: Your root item has to be a Window.");
return -1;
}window->show();
return app.exec();@
-
-
[quote author="t3685" date="1379689723"]You just need to create one C++ class for each screen.[/quote] True :) It seems good. I'll try once.
-
@vladstelmahovsky: I'm using the way as in "QtQuick2 Built In types" while creating a new project in QtCreator.
How is the way you told is different from the one I'm using? Which is advantageous. -
you have more control over engine, context and root object