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 sierdzio
    7 May 2019, 10:02

    Simplest way to reload a loader:

    // In some JS function, like button click handler:
    loaderRecord.source = ""
    loaderRecord.source = "Record/Record.qml"
    

    But I suspect you are asking about something else, right?

    J Offline
    J Offline
    J.Hilk
    Moderators
    wrote on 7 May 2019, 11:07 last edited by J.Hilk 5 Jul 2019, 11:15
    #3

    @sierdzio I haven't tested it, but shouldn't this be the same, as setting the active property to false, and to true again ?


    Edit:
    jup made a small test:

    ApplicationWindow {
        id:root
        visible:true
        width:500; height:500
    
        Button {
            id:btn
            anchors.top: parent.top
            anchors.left: parent.left
            anchors.right: parent.right
            height:  50
    
            onClicked: {
                load.active = !load.active
    
                load.active = !load.active
            }
        }
    
        Loader{
            id:load
            anchors.left: parent.left
            anchors.right: parent.right
            anchors.bottom: parent.bottom
            anchors.top: btn.bottom
    
            source: "TestFile.qml"
        }
    }
    
    //TestFile.qml
    import QtQuick 2.0
    
    Rectangle {
        color: "blue"
    
        Component.onCompleted: console.log("completed")
        Component.onDestruction: console.log("Destructed")
    
    }
    

    works fine enough, completed and destructed is printed each time


    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
    1
    • D Offline
      D Offline
      Dylan_Alt.
      wrote on 7 May 2019, 11:48 last edited by
      #4

      Thanks for your response !

      Both of your solution work, but it seems that the application keeps the initial qml file in memory. If I change my code live and reload it, my app will still load the file without the new modification.

      J 1 Reply Last reply 7 May 2019, 12:19
      0
      • D Dylan_Alt.
        7 May 2019, 11:48

        Thanks for your response !

        Both of your solution work, but it seems that the application keeps the initial qml file in memory. If I change my code live and reload it, my app will still load the file without the new modification.

        J Offline
        J Offline
        J.Hilk
        Moderators
        wrote on 7 May 2019, 12:19 last edited by
        #5

        @Dylan_Alt. that's because the component cache is not cleared.

        But I don't know how to force this from QML side. Maybe forcing the garbage collector to run in-between ? gc()

        usually you would call clearComponentCache on your QQmlApplicationEngine inside you main.cpp for that.

        Or that's where I do it ;)


        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
        3
        • 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