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
QtWS25 Last Chance

Reload a Loader on button click

Scheduled Pinned Locked Moved Solved QML and Qt Quick
qmlloader
16 Posts 6 Posters 10.8k Views
  • 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.
  • 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