Design Patterns QML & C++



  • Are there any good Design Patterns for QML & C++ ?

    I mean, I understood the sense of QML. It's there to separate UI from Logic.
    But I have some problems...
    ...Example given:

    • Problem: I have a QML-ListView which should be filled from the C++-Code, by loading the data from a SQL database.
      Question: What's the solution? How can I fill the QML-ListView with the given data from the C++-Code?

    • Problem: The user clicks on one of the items in the ListView. The C++-Code must know which item the user clicked.
      Question: How does the C++-Code know which item was clicked by the user?

    • Problem: The e.g.: MyMainMenu.qml has lots of nested elements. Some elements have signals, which will be raised if the user clicks on it.
      Question: How does the C++-Code connects to these signals?

    • Problem: The UI has a main menu. If the user clicks on e.g.: News, the C++-Code receives the Click-Signal and shows the News.qml file.
      Question: How should I implement such a concept? I mean: How could I switch from one .qml file to the other? (With a nice effect).

    It would be awesome if you could provide examples to these questions.

    Thanks,
    lunatic



  • This is quite a question. Pretty much each of those problems deserves its own thread, or better yet a wiki page.

    Regarding:

    bq. Some elements have signals, which will be raised if the user clicks on it.
    Question: How does the C++-Code connects to these signals?

    C++ can't directly connect to QML signals, so I suggest handling the signals in QML and calling the slot/method on the C++ object.

    Example:
    @onClicked: { _someCPPObject.somethingClicked() }@

    (it is a good convention to prefix your C++ objects in QML with an underscore)

    bq. Problem: The UI has a main menu. If the user clicks on e.g.: News, the C++-Code receives the Click-Signal and shows the News.qml file.
    Question: How should I implement such a concept? I mean: How could I switch from one .qml file to the
    As for switching between QML files. This is a complex topic. other? (With a nice effect).

    As for switching between QML files. This is a complex topic. First, don't think of it as "switching" QML files.

    Instead, your News.qml file should declare a single QML Element (probably an Item element), and some other QML file (like your mainwindow.qml) will include it with:

    @ News {
    // news properties and anchors, etc
    }@

    You should think of your QML UI as a tree of QML elements that is loaded all at once by loading your main QML source. You accomplish switching between screens (not files) by effectively changing which node in the tree is currently displayed. Do this by setting the 'visibility' property on your QML elements.

    Personally, I like to have a global C++ object (where global means accessible in QML) with an enum for each screen. Then I have a currentScreen Q_PROPERTY and set my QML elements like so:

    @
    SomeElement {
    visible: _screenInfo.currentScreen == ScreenInfo.SomeEnum
    // ...
    }
    @

    Note that I am using the declarative model here. No where do I need an if statement like:

    @if (currentScreen() != ScreenInfo.SomeEnum ) {
    SomeElement.visible = false
    };@

    That kind of code gets messy fast, and is unnecessary in QML.

    The screens themselves can be a composition of many sub-elements. Thinking in terms of a tree is important.

    Handling the flow between screens can be a daunting task. Using a QStateMachine makes it much easier and maintainable. Unfortunately I don't know of any wiki articles or guides explaining how to do this, but I did find "this mailing list post":http://www.mail-archive.com/qt-qml@trolltech.com/msg01739.html that is a good primer.



  • All problems can be solved if you go with UI-Controller approach. Here QML is your UI, keep it as dump as possible. Controller is a QObject based class exposing required methods as slots, signals, Q_INVOKABLE and Q_PROPERTY.

    Now inject each controller into the qml as a QtObject property and handle the logic accordingly.

    For ListView ( I would say models in QML ), derive your class from QAbstractListModel and handle it accordingly. You can also create a simple count based model also. See "here":http://developer.qt.nokia.com/forums/viewthread/8929/#53644.



  • All of your questions are answered in a common topic "Extending QML using C++"

    http://doc.qt.nokia.com/4.7-snapshot/qml-extending.html
    http://doc.qt.nokia.com/4.7-snapshot/qdeclarativemodels.html#c-data-models

    And "Using QML in C++"
    http://doc.qt.nokia.com/latest/qtbinding.html

    The pages have examples as well.



  • If you are just going to load the Listview from DB, you can simply use the SQL support in QML itself. But, if there are going to be any manipulations, you gotta go for C++, personally I feel, the ObjectListModel and QStringList model are much easier to use and write code.

    If the user clicks on the ListView item: you should have defined a delegate for that ListView with a MouseArea, that will send the "text" or whatever the delegate has, to the CPP method. TO implement this, you should follow Casey's rule.

    Follow Kypeli's "Using QML..." link for achieving your third use case.

    For the switching QML (like, page transition effect), it is always better to go for Dynamically loaded QML components, because I have used a dirty way to achieve this and the application consumes 20 MB of RAM for it. I would suggest you to go for Opacity based transition, i.e. decrease the opacity of the first page and then increase the Opacity of the second page. If the switching is too infrequent to maintain the Pages in the memory, you can load all the pages dynamically and destroy them as desired.

    If you search around the documentation, you can find examples for all your use cases with fine examples.



  • [quote author="raja26" date="1315331802"]If you are just going to load the Listview from DB, you can simply use the SQL support in QML itself. But, if there are going to be any manipulations, you gotta go for C++, personally I feel, the ObjectListModel and QStringList model are much easier to use and write code.[/quote]

    There is only SQLite support in QML. In the future I don't know. I would go with "QAbstractListModel":http://doc.qt.nokia.com/latest/qabstractlistmodel.html .



  • [quote author="minimoog77" date="1315395490"]
    There is only SQLite support in QML. In the future I don't know. I would go with "QAbstractListModel":http://doc.qt.nokia.com/latest/qabstractlistmodel.html . [/quote]
    Yes, indeed there is SQLite support alone. I though you were developing for mobile.

    All the best.


  • Qt Champions 2016

    Action-Dispatcher Design Pattern for QML — Medium

    This article is my answer to problem 2 & 3.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.