Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Loader vs ?



  • So I have a GUI in QML made up that uses loaders to switch between several pages of gauges. all my incoming information is being processed in several C++ classes and sent to the GUI. It's all working as I expected, except, I have learned that when a page is 'unloaded', it is no longer active at all, so that when I switch to each page, the page restarts and each gauge has to wait to receive the next incoming data before becoming active (hope that makes sense) . I should have realized this from the beginning, but being a newbie, it took actually making the program and watching it work for me to understand the behavior.

    So now I am wondering how can I keep all my gauges on each page 'active' so that when I switch to the page, the gauge is reading the last received bit of information?

    I was wondering about hiding/showing the pages instead of loading and unloading? I also saw this:

    https://stackoverflow.com/questions/12601520/qml-change-views-on-click

    and was wondering if creating a class derived from QDeclaritiveView would start me down the right path? Don't really understand that one yet, but willing to dive into it!

    Any advice appreciated!


  • Moderators

    You can use a SwipeView which does not unload pages that are not visible.

    Keep in mind, though, that keeping all your pages alive when application runs will impact performance - your CPU will have to handle all these pages at once.

    Perhaps a better approach would be to add one layer to your C++ logic: something that would keep last reading in memory for views that are being loaded.



  • @sierdzio - thank you as always for taking the time to answer.

    I'll investigate a SwipeView...

    Wouldn't having a 'last value' layer have the same issue as what I'm facing? The gauges would have to instantiate, then populate the value from the new layer...?


  • Banned

    This post is deleted!

  • Moderators

    @MScottM said in Loader vs ?:

    @sierdzio - thank you as always for taking the time to answer.

    I'll investigate a SwipeView...

    Wouldn't having a 'last value' layer have the same issue as what I'm facing? The gauges would have to instantiate, then populate the value from the new layer...?

    Yes, they would have to instantiate. But (well, depending on how you write it) would have the "real" values readily available - they would not need to wait for another data packet to come, be processed by your C++ logic etc.

    In fact, if you use your C++ "cache" layer right in the QML for your various screens, then QML engine would be forced to load the cached values immediately - gauges will immediately use the correct (cached) values. So, for a simple example:

    // Old:
    Gauge {
      value: 0 // (default value)
    }
    // New:
    Gauge {
      value: MyCache.value
    }
    


  • @sierdzio

    Aha - I'll experiment with that. Thanks!!



  • Hi,

    How are you delivering your c++ data to QML?

    For example I just recently started using QML for UI and using Q_PROPERTY macros even when I destroy and reconstruct views in QML the data persists. In fact I had the exact opposite behavior where my page reloaded and all the information was still typed in! So I called an invokable method on view destruction/load to fix that issue and clear c++ variables.



  • @MrShawn

    I have several different types of data being delivered via UDP messages on an ethernet bus. The data passes through a 'message sorter' (c++ class) that decides what type of message it is and delivers it to another class (one for each type of message). There, each message is parsed for the data and the data is emitted with a signal. In my main.cpp, I use 'setContextProperty' for each message class, and in QML, I use Connections{onMessageSignal...} to watch the signals.

    I originally tried to use Q_PROPERTY(Variable variable READ variable WRITE setVariable NOTIFY variableChanged), but could never quite get it working and got frustrated and moved on. Since, though I have wondered it it would have the behavior I'm looking for - that you describe.

    -Scott



  • @MScottM said in Loader vs ?:

    I originally tried to use Q_PROPERTY(Variable variable READ variable WRITE setVariable NOTIFY variableChanged), but could never quite get it working and got frustrated and moved on. Since, though I have wondered it it would have the behavior I'm looking for - that you describe.

    It should provide you with what you are looking for. When you tried to get it working what was not working about it? I embed my onChanged signals into the setter methods and check if the variable has actually changed.

    I have a UIBridge class that passively grabs signals and updates its copy of the variables locally. My QML is connected to the bridge and my QML implementation is as simple as:

    Text {
             id: opName
             text: UIBridge.loading ? "" : UIBridge.user.operatorName
    }
    

    If you notice I even have boolean variables I am referencing for conditional stuff as well. By simply setting my c++ boolean "loading" to true I clear what is being displayed in the text component. QML knows the boolean change and handles it accordingly.

    I will add doing Q_PROPERTY() with custom classes that inherit QObject does not seem to work very well... Due to the copy constructor being disabled. I haven't figured out the best way to deal with this but my work around was to use pointers.

    Q_PROPERTY(Operator* user READ getUser NOTIFY userChanged)
    Q_PROPERTY(Shoporder* shoporder READ getShoporder NOTIFY shoporderChanged)
    Q_PROPERTY(Part* part READ getPart NOTIFY partChanged)
    Q_PROPERTY(EquipmentSettings* equipmentSettings READ getEquipmentSettings NOTIFY equipmentSettingsChanged)
    Q_PROPERTY(Limits* limits READ getLimits NOTIFY limitsChanged)
    

    Where my getters return the pointer (obviously). Other more base data types work just fine with the Q_PROPERTY macro.

    To connect my class instance to QML have these lines in cpp:

        QQmlApplicationEngine engine;
        /* add the bridge to the QML engine */
        UIBridge uiBridge;
        engine.rootContext()->setContextProperty("UIBridge",&uiBridge);  //in QML my object name is "UIBridge"
       
        /* start the engine */
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    


  • Hi @MrShawn,

    Thank you for sharing! It sounds like how you handled the interface would work for me. If you don't mind me saying so, your UIBridge class sounds like the extra layer, or cache, that @sierdzio was suggesting. I'll do some experimenting with this.

    Thanks!!



  • I'm relatively new to Qt and I have made a project similar to yours. So far, I've made a Qt Quick App with a circular gauge. The gauge is currently animating using "NumberAnimation". I would like to know how I could set up the C++ classes to make my gauge accept values over UDP Ethernet, in order to make it animate.

    Thank you!


  • Lifetime Qt Champion

    @LoonyToons Please do not ask same question in several threads.
    https://forum.qt.io/topic/111605/gauge-controlled-by-udp-ethernet


Log in to reply