Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Reload a Loader on button click
Forum Updated to NodeBB v4.3 + New Features

Reload a Loader on button click

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlloader
16 Posts 6 Posters 11.1k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    sierdzio
    Moderators
    wrote on 7 May 2019, 19:03 last edited by
    #6

    Note that the cached properties will be cleared if the source or sourceComponent is changed after calling this function but prior to setting the loader active.

    That's from https://doc.qt.io/qt-5/qml-qtquick-loader.html. So the solution might be to get the right combination of active: false, then set source, then 'active: true`, but it sounds very hacky. What @J-Hilk proposed seems better.

    (Z(:^

    1 Reply Last reply
    2
    • F Offline
      F Offline
      fcarney
      wrote on 7 May 2019, 19:17 last edited by
      #7

      Would creating dynamic QML objects work better than using a Loader?
      https://doc.qt.io/qt-5/qtqml-javascript-dynamicobjectcreation.html

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Dylan_Alt.
        wrote on 10 May 2019, 07:42 last edited by
        #8

        Hi,

        sorry for the late response, I had a lot of other stuff to do.
        I tried with gc() and the hacky way, and a combination of both, and the result is the same as before.
        I haven't try fcarney's solution yet, I will do it when I will have a some time, and tell you if it worked.

        Thanks

        1 Reply Last reply
        0
        • J Offline
          J Offline
          J.Hilk
          Moderators
          wrote on 10 May 2019, 07:54 last edited by
          #9

          Here's how I do it,
          maybe it's of help for your case:

          //QuickWidget.h
          #ifndef QUICKWINDOW_H
          #define QUICKWINDOW_H
          
          #include <QQuickWindow>
          #include <QIcon>
          
          class QuickWindow : public QQuickWindow
          {
              Q_OBJECT
          public:
              explicit QuickWindow(QQuickWindow *parent = nullptr) : QQuickWindow(parent) {}
          
          signals:
              Q_INVOKABLE void reloadQML();
          
          };
          
          #endif // QUICKWINDOW_H
          
          //main.cpp
          #include <QApplication>
          #include <QQmlApplicationEngine>
          
          #include "quickwindow.h"
          
          void clearAndReload( QQmlApplicationEngine &engine){
              for(QObject *obj : engine.rootObjects()){
                  engine.rootObjects().removeOne(obj);
                  obj->deleteLater();
              }
              engine.clearComponentCache();
              engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
          
              for(QObject *obj : engine.rootObjects()){
                  QuickWindow *window = qobject_cast<QuickWindow*>(obj);
                  if(window)QObject::connect(window, &QuickWindow::reloadQML, &engine,[&engine]{clearAndReload(engine);});
              }
          }
          
          int main(int argc, char *argv[])
          {
              QApplication app(argc, argv);
          
          
              qmlRegisterType<QuickWindow>("QuickWindow", 1, 0, "QuickWindow");
              QQmlApplicationEngine engine;
          
              engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
              if (engine.rootObjects().isEmpty())
                  return -1;
          
              for(QObject *obj : engine.rootObjects()){
                  QuickWindow *window = qobject_cast<QuickWindow*>(obj);
                  if(window) QObject::connect(window, &QuickWindow::reloadQML, &engine,[&engine]{clearAndReload(engine);});
              }
          
          
              return app.exec();
          }
          
          //main.qml
          import QtQuick 2.12
          import QtQuick.Controls 2.5
          
          import QuickWindow 1.0
          
          QuickWindow {
              id:root
              visible:true
              width:500; height:500
          
              Component.onCompleted: console.log("Window created")
          
              Shortcut{
                  sequence: "F5"
                  onActivated: {
                      console.log("Reload")
                      reloadQML()
                  }
              }
          }
          
          

          Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


          Q: What's that?
          A: It's blue light.
          Q: What does it do?
          A: It turns blue.

          D 1 Reply Last reply 14 May 2019, 12:34
          0
          • J J.Hilk
            10 May 2019, 07:54

            Here's how I do it,
            maybe it's of help for your case:

            //QuickWidget.h
            #ifndef QUICKWINDOW_H
            #define QUICKWINDOW_H
            
            #include <QQuickWindow>
            #include <QIcon>
            
            class QuickWindow : public QQuickWindow
            {
                Q_OBJECT
            public:
                explicit QuickWindow(QQuickWindow *parent = nullptr) : QQuickWindow(parent) {}
            
            signals:
                Q_INVOKABLE void reloadQML();
            
            };
            
            #endif // QUICKWINDOW_H
            
            //main.cpp
            #include <QApplication>
            #include <QQmlApplicationEngine>
            
            #include "quickwindow.h"
            
            void clearAndReload( QQmlApplicationEngine &engine){
                for(QObject *obj : engine.rootObjects()){
                    engine.rootObjects().removeOne(obj);
                    obj->deleteLater();
                }
                engine.clearComponentCache();
                engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
            
                for(QObject *obj : engine.rootObjects()){
                    QuickWindow *window = qobject_cast<QuickWindow*>(obj);
                    if(window)QObject::connect(window, &QuickWindow::reloadQML, &engine,[&engine]{clearAndReload(engine);});
                }
            }
            
            int main(int argc, char *argv[])
            {
                QApplication app(argc, argv);
            
            
                qmlRegisterType<QuickWindow>("QuickWindow", 1, 0, "QuickWindow");
                QQmlApplicationEngine engine;
            
                engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
                if (engine.rootObjects().isEmpty())
                    return -1;
            
                for(QObject *obj : engine.rootObjects()){
                    QuickWindow *window = qobject_cast<QuickWindow*>(obj);
                    if(window) QObject::connect(window, &QuickWindow::reloadQML, &engine,[&engine]{clearAndReload(engine);});
                }
            
            
                return app.exec();
            }
            
            //main.qml
            import QtQuick 2.12
            import QtQuick.Controls 2.5
            
            import QuickWindow 1.0
            
            QuickWindow {
                id:root
                visible:true
                width:500; height:500
            
                Component.onCompleted: console.log("Window created")
            
                Shortcut{
                    sequence: "F5"
                    onActivated: {
                        console.log("Reload")
                        reloadQML()
                    }
                }
            }
            
            
            D Offline
            D Offline
            Dylan_Alt.
            wrote on 14 May 2019, 12:34 last edited by
            #10

            @J.Hilk I cannot use any C++ code :( I'm using QML in an external software, I can't link both C++ and QML.

            I tried to create / delete my objects dynamically like that :

            main.qml

            [...]
            StackLayout {
            [...]
                    Loader{
                        id: loaderTestReload
                        source: "tab1.qml"
                    }
            [...]
                }
            

            tab1.qml is use to create my object :

            Item {
                id: tab1
            
                property var compo
            
                Component.onCompleted: init()
                
                function init()
                {
                    var component = Qt.createComponent("tab1_qml.qml")
                    component.createObject(tab1)
                    compo = component
                }
                function reload()
                {
                    compo.destroy()
                    init()
                }
            }
            

            and then I have the main component, with 2 buttons and a text :

            Item {
                id: tab1qml
            
                property int value: 0
                Button{
                    id: button1
                    text: tab1qml.value
                    onClicked: value++
                }
                Button{
                    y: button1.height
                    text: "reload"
                    onClicked: tab1.reload()
                }
                Text{
                    y: button1.height*2
                    text: "reset ?"
                }
            }
            

            When I press the reload button, the component is reloaded, but as before, my app keeps the file in memory. If I change my text, it will remain as it was.
            I will take a look at the example, it uses createQmlObject() instead of createComponent(). Maybe I can store the content of the file and send it via createQmlObject().

            J 1 Reply Last reply 14 May 2019, 12:42
            0
            • D Dylan_Alt.
              14 May 2019, 12:34

              @J.Hilk I cannot use any C++ code :( I'm using QML in an external software, I can't link both C++ and QML.

              I tried to create / delete my objects dynamically like that :

              main.qml

              [...]
              StackLayout {
              [...]
                      Loader{
                          id: loaderTestReload
                          source: "tab1.qml"
                      }
              [...]
                  }
              

              tab1.qml is use to create my object :

              Item {
                  id: tab1
              
                  property var compo
              
                  Component.onCompleted: init()
                  
                  function init()
                  {
                      var component = Qt.createComponent("tab1_qml.qml")
                      component.createObject(tab1)
                      compo = component
                  }
                  function reload()
                  {
                      compo.destroy()
                      init()
                  }
              }
              

              and then I have the main component, with 2 buttons and a text :

              Item {
                  id: tab1qml
              
                  property int value: 0
                  Button{
                      id: button1
                      text: tab1qml.value
                      onClicked: value++
                  }
                  Button{
                      y: button1.height
                      text: "reload"
                      onClicked: tab1.reload()
                  }
                  Text{
                      y: button1.height*2
                      text: "reset ?"
                  }
              }
              

              When I press the reload button, the component is reloaded, but as before, my app keeps the file in memory. If I change my text, it will remain as it was.
              I will take a look at the example, it uses createQmlObject() instead of createComponent(). Maybe I can store the content of the file and send it via createQmlObject().

              J Offline
              J Offline
              J.Hilk
              Moderators
              wrote on 14 May 2019, 12:42 last edited by
              #11

              @Dylan_Alt.

              Indulge me for a bit, as I have not done this before. How do you start a QML application without a main- function?


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              D 1 Reply Last reply 14 May 2019, 13:04
              0
              • J J.Hilk
                14 May 2019, 12:42

                @Dylan_Alt.

                Indulge me for a bit, as I have not done this before. How do you start a QML application without a main- function?

                D Offline
                D Offline
                Dylan_Alt.
                wrote on 14 May 2019, 13:04 last edited by Dylan_Alt.
                #12

                @J.Hilk I don't how it's made behind. The software uses blocks to code (like Unreal Engine for example, but at a much higher level than simple instructions). One of these blocks is a QML Viewer, where I can set a main.qml file, up to 32 input property and as many outputs as I want. I don't have any control of what happens when the full application is started.

                J 1 Reply Last reply 14 May 2019, 13:13
                1
                • D Dylan_Alt.
                  14 May 2019, 13:04

                  @J.Hilk I don't how it's made behind. The software uses blocks to code (like Unreal Engine for example, but at a much higher level than simple instructions). One of these blocks is a QML Viewer, where I can set a main.qml file, up to 32 input property and as many outputs as I want. I don't have any control of what happens when the full application is started.

                  J Offline
                  J Offline
                  J.Hilk
                  Moderators
                  wrote on 14 May 2019, 13:13 last edited by
                  #13

                  @Dylan_Alt.
                  alight,

                  that's unfortunate, as it limits your options quite heavily.


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  1 Reply Last reply
                  0
                  • D Offline
                    D Offline
                    Dylan_Alt.
                    wrote on 24 May 2019, 06:50 last edited by
                    #14

                    I took my time to test several things and I found something that worked :
                    I used createQmlObject(), to load the content of the file, instead of createComponent(). Here is how it looks like :

                    Tab1.qml :

                    Item {
                        id: tab1
                    
                        property var compo
                    
                        Component.onCompleted: init()
                    
                        function init()
                        {
                            var xhr = new XMLHttpRequest;
                            var response
                            xhr.open("GET", "tab1_qml.qml");
                            xhr.onreadystatechange = function() {
                                if (xhr.readyState == XMLHttpRequest.DONE) {
                                    response = xhr.responseText;
                                    compo = Qt.createQmlObject(response, tab1,"tab1_qml.qml")
                                }
                            };
                            xhr.send(); // begin the request
                        }
                        function reload()
                        {
                            compo.destroy()
                            init()
                        }
                    }
                    

                    tab1_qml.qml :

                    Item {
                        id: tab1qml
                    
                        property int value: 0
                        Button{
                            id: button1
                            text: tab1qml.value
                            onClicked: value++
                        }
                        Button{
                            y: button1.height
                            text: "reload"
                            onClicked: tab1.reload()
                        }
                        Text{
                            y: button1.height*2
                            text: "reset ?"
                        }
                    }
                    
                    

                    When I modify my tab1_qml.qml and clic the reload button, it works.
                    But bad news, it works well on my software, but it doesn't work on QtCreator. As far as I understand, it's because the file is loaded from the ressource, the solution may be to take an external qml file.
                    Anyway, my problem is solved.

                    Thanks everyone who responsed.

                    9 1 Reply Last reply 13 Jul 2020, 19:44
                    1
                    • D Dylan_Alt.
                      24 May 2019, 06:50

                      I took my time to test several things and I found something that worked :
                      I used createQmlObject(), to load the content of the file, instead of createComponent(). Here is how it looks like :

                      Tab1.qml :

                      Item {
                          id: tab1
                      
                          property var compo
                      
                          Component.onCompleted: init()
                      
                          function init()
                          {
                              var xhr = new XMLHttpRequest;
                              var response
                              xhr.open("GET", "tab1_qml.qml");
                              xhr.onreadystatechange = function() {
                                  if (xhr.readyState == XMLHttpRequest.DONE) {
                                      response = xhr.responseText;
                                      compo = Qt.createQmlObject(response, tab1,"tab1_qml.qml")
                                  }
                              };
                              xhr.send(); // begin the request
                          }
                          function reload()
                          {
                              compo.destroy()
                              init()
                          }
                      }
                      

                      tab1_qml.qml :

                      Item {
                          id: tab1qml
                      
                          property int value: 0
                          Button{
                              id: button1
                              text: tab1qml.value
                              onClicked: value++
                          }
                          Button{
                              y: button1.height
                              text: "reload"
                              onClicked: tab1.reload()
                          }
                          Text{
                              y: button1.height*2
                              text: "reset ?"
                          }
                      }
                      
                      

                      When I modify my tab1_qml.qml and clic the reload button, it works.
                      But bad news, it works well on my software, but it doesn't work on QtCreator. As far as I understand, it's because the file is loaded from the ressource, the solution may be to take an external qml file.
                      Anyway, my problem is solved.

                      Thanks everyone who responsed.

                      9 Offline
                      9 Offline
                      99hats
                      wrote on 13 Jul 2020, 19:44 last edited by
                      #15

                      @Dylan_Alt I realize this is a pretty old thread and this is a pretty hacky response, but it appears to work for both local and remote files.

                      onClicked {
                        myLoader.source = "MyLocalOrRemoteFile.qml?"+Math.random()
                      }
                      
                      _ 1 Reply Last reply 19 May 2023, 11:48
                      2
                      • 9 99hats
                        13 Jul 2020, 19:44

                        @Dylan_Alt I realize this is a pretty old thread and this is a pretty hacky response, but it appears to work for both local and remote files.

                        onClicked {
                          myLoader.source = "MyLocalOrRemoteFile.qml?"+Math.random()
                        }
                        
                        _ Offline
                        _ Offline
                        _nezticle
                        wrote on 19 May 2023, 11:48 last edited by
                        #16

                        @99hats lol, that is a good solution and I can confirm that it does work. (though since it's being cheeky, it likely just fills up the component cache)

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved