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. Blocked gui does not draw an qml item?

Blocked gui does not draw an qml item?

Scheduled Pinned Locked Moved Solved QML and Qt Quick
15 Posts 6 Posters 2.2k 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.
  • PowerNowP Offline
    PowerNowP Offline
    PowerNow
    wrote on last edited by PowerNow
    #1

    Hi,
    I have a problem with the exact timing of signals in qml.

    Problem:

    1. press on a button
    2. make iRect visible
    3. start heavyFunct() in C++ which blocks the Gui
    MouseArea {                   
           onClicked: {
                 console.log("onClicked");
                 iRect.visible = true;
         }
    
         Rectangle {
                  id: iRect
                  visible: false
                  anchors.fill: parent
                  color: "green"
    
                  onVisibleChanged: {
                         if(visible) {
                               console.log("onVisibleChanged");
                               heavyFunct();
                         }
                 }
          }
    }
    

    The signals/slots are called in the correction direction but on the screen iRect does not become visible before heavyFunct() is started. So it seems that the signals in Qml are called with the instruction in the code but not after the item was really rendered from the graphiccard.

    Is there a way to force an item to be drawn before continue with the next instruction?

    Currently I'm not able to move the heavyFunct() in a separate thread.

    What goes wrong here or how can I solve this problem?

    J.HilkJ ODБOïO KroMignonK 3 Replies Last reply
    0
    • PowerNowP PowerNow

      Hi,
      I have a problem with the exact timing of signals in qml.

      Problem:

      1. press on a button
      2. make iRect visible
      3. start heavyFunct() in C++ which blocks the Gui
      MouseArea {                   
             onClicked: {
                   console.log("onClicked");
                   iRect.visible = true;
           }
      
           Rectangle {
                    id: iRect
                    visible: false
                    anchors.fill: parent
                    color: "green"
      
                    onVisibleChanged: {
                           if(visible) {
                                 console.log("onVisibleChanged");
                                 heavyFunct();
                           }
                   }
            }
      }
      

      The signals/slots are called in the correction direction but on the screen iRect does not become visible before heavyFunct() is started. So it seems that the signals in Qml are called with the instruction in the code but not after the item was really rendered from the graphiccard.

      Is there a way to force an item to be drawn before continue with the next instruction?

      Currently I'm not able to move the heavyFunct() in a separate thread.

      What goes wrong here or how can I solve this problem?

      J.HilkJ Offline
      J.HilkJ Offline
      J.Hilk
      Moderators
      wrote on last edited by
      #2

      hi @PowerNow

      after setting your Item to visible = true, you wan't to listen to the
      frameSwapped signal

      After that, your Item should be drawn on the screen.


      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
      2
      • PowerNowP PowerNow

        Hi,
        I have a problem with the exact timing of signals in qml.

        Problem:

        1. press on a button
        2. make iRect visible
        3. start heavyFunct() in C++ which blocks the Gui
        MouseArea {                   
               onClicked: {
                     console.log("onClicked");
                     iRect.visible = true;
             }
        
             Rectangle {
                      id: iRect
                      visible: false
                      anchors.fill: parent
                      color: "green"
        
                      onVisibleChanged: {
                             if(visible) {
                                   console.log("onVisibleChanged");
                                   heavyFunct();
                             }
                     }
              }
        }
        

        The signals/slots are called in the correction direction but on the screen iRect does not become visible before heavyFunct() is started. So it seems that the signals in Qml are called with the instruction in the code but not after the item was really rendered from the graphiccard.

        Is there a way to force an item to be drawn before continue with the next instruction?

        Currently I'm not able to move the heavyFunct() in a separate thread.

        What goes wrong here or how can I solve this problem?

        ODБOïO Offline
        ODБOïO Offline
        ODБOï
        wrote on last edited by ODБOï
        #3

        @PowerNow said in Blocked gui does not draw an qml item?:

        Currently I'm not able to move the heavyFunct() in a separate thread.

        Maybe this can help you for that

        //the function you have to call from qml
        void heavyFnc(){
                for(int tt = 100000;tt>1;tt--){
                    qDebug()<<tt;
                }
            }
        
        //make it static 
        static void heavyFnc(){
                for(int tt = 100000;tt>1;tt--){
                    qDebug()<<tt;
                }
            }
        
        //create Q_INVOKABLE to wrap it and move it to new Qthread
            Q_INVOKABLE void doHeavyFnc(){
                QThread *t = QThread::create(heavyFnc);
                t->start();
            }
        // you have to delete *t somewhere
        
        1 Reply Last reply
        0
        • PowerNowP PowerNow

          Hi,
          I have a problem with the exact timing of signals in qml.

          Problem:

          1. press on a button
          2. make iRect visible
          3. start heavyFunct() in C++ which blocks the Gui
          MouseArea {                   
                 onClicked: {
                       console.log("onClicked");
                       iRect.visible = true;
               }
          
               Rectangle {
                        id: iRect
                        visible: false
                        anchors.fill: parent
                        color: "green"
          
                        onVisibleChanged: {
                               if(visible) {
                                     console.log("onVisibleChanged");
                                     heavyFunct();
                               }
                       }
                }
          }
          

          The signals/slots are called in the correction direction but on the screen iRect does not become visible before heavyFunct() is started. So it seems that the signals in Qml are called with the instruction in the code but not after the item was really rendered from the graphiccard.

          Is there a way to force an item to be drawn before continue with the next instruction?

          Currently I'm not able to move the heavyFunct() in a separate thread.

          What goes wrong here or how can I solve this problem?

          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by
          #4

          @PowerNow If you don't want to lock the GUI, you have to move heavyFunct() execution in another thread. There are no other option in my eyes.

          To move the function execution to another thread, there a many way to do, but the easiest way for me is using QtConcurrent:

          
          class MyClass: public QObject
           {
              Q_OBJECT
          
          ...
          private:
              void heavyFunct();
          ...
          public:
              Q_INVOKABLE void doHeavyFnc()
             {  
                  if(!m_heavyInProgress.isRunning())
                  {
                      QtConcurrent::run(this, &MyClass::heavyFunct);
                  }
              }
          ...
          private:
               QFuture<void> m_heavyInProgress;
          

          Hope this could help you.

          It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

          1 Reply Last reply
          0
          • PowerNowP Offline
            PowerNowP Offline
            PowerNow
            wrote on last edited by
            #5

            Thxs to all of you!
            But as I mentioned unfortunately I can't move at the moment the heavyFunct() (its a QFramebufferobject loaded via Loader which needs a lot of memory and power) into a separat threat, currently I'm looking for a simple solution.
            @J.Hilk: Yes this works thxs! But It's an app using a Videoframbuffer (highest possible frame rate) and i think only for this button always check the frameSwapped signal does not make me feel good. Or is there a way to check it only once?

            I only want to visually show the user if he press on the button, that he have to wait and not press again during the loading of the heavyFunct(). Is there no way to force Qml to update the scenegraph and give response? The locking of the gui is not that problem.

            raven-worxR T KroMignonK 3 Replies Last reply
            0
            • PowerNowP PowerNow

              Thxs to all of you!
              But as I mentioned unfortunately I can't move at the moment the heavyFunct() (its a QFramebufferobject loaded via Loader which needs a lot of memory and power) into a separat threat, currently I'm looking for a simple solution.
              @J.Hilk: Yes this works thxs! But It's an app using a Videoframbuffer (highest possible frame rate) and i think only for this button always check the frameSwapped signal does not make me feel good. Or is there a way to check it only once?

              I only want to visually show the user if he press on the button, that he have to wait and not press again during the loading of the heavyFunct(). Is there no way to force Qml to update the scenegraph and give response? The locking of the gui is not that problem.

              raven-worxR Offline
              raven-worxR Offline
              raven-worx
              Moderators
              wrote on last edited by
              #6

              @PowerNow said in Blocked gui does not draw an qml item?:

              Or is there a way to check it only once?

              make the slot connected to the frameSwapped signal disconnect itself when it gets called

              --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
              If you have a question please use the forum so others can benefit from the solution in the future

              1 Reply Last reply
              1
              • PowerNowP PowerNow

                Thxs to all of you!
                But as I mentioned unfortunately I can't move at the moment the heavyFunct() (its a QFramebufferobject loaded via Loader which needs a lot of memory and power) into a separat threat, currently I'm looking for a simple solution.
                @J.Hilk: Yes this works thxs! But It's an app using a Videoframbuffer (highest possible frame rate) and i think only for this button always check the frameSwapped signal does not make me feel good. Or is there a way to check it only once?

                I only want to visually show the user if he press on the button, that he have to wait and not press again during the loading of the heavyFunct(). Is there no way to force Qml to update the scenegraph and give response? The locking of the gui is not that problem.

                T Offline
                T Offline
                Tom_H
                wrote on last edited by
                #7

                @PowerNow I solved a similar issue by using a Timer.

                PowerNowP 1 Reply Last reply
                1
                • PowerNowP PowerNow

                  Thxs to all of you!
                  But as I mentioned unfortunately I can't move at the moment the heavyFunct() (its a QFramebufferobject loaded via Loader which needs a lot of memory and power) into a separat threat, currently I'm looking for a simple solution.
                  @J.Hilk: Yes this works thxs! But It's an app using a Videoframbuffer (highest possible frame rate) and i think only for this button always check the frameSwapped signal does not make me feel good. Or is there a way to check it only once?

                  I only want to visually show the user if he press on the button, that he have to wait and not press again during the loading of the heavyFunct(). Is there no way to force Qml to update the scenegraph and give response? The locking of the gui is not that problem.

                  KroMignonK Offline
                  KroMignonK Offline
                  KroMignon
                  wrote on last edited by
                  #8

                  @PowerNow said in Blocked gui does not draw an qml item?:

                  (its a QFramebufferobject loaded via Loader

                  I'm not sure to understand how this works. Is the Loader a QML Loader instance?
                  Why is this loader not set asynchronous to true?

                  Loader {
                      source: "myHeadyComponent.qml"
                      asynchronous: true
                      visible: status == Loader.Ready
                  }
                  

                  It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                  PowerNowP 1 Reply Last reply
                  0
                  • KroMignonK KroMignon

                    @PowerNow said in Blocked gui does not draw an qml item?:

                    (its a QFramebufferobject loaded via Loader

                    I'm not sure to understand how this works. Is the Loader a QML Loader instance?
                    Why is this loader not set asynchronous to true?

                    Loader {
                        source: "myHeadyComponent.qml"
                        asynchronous: true
                        visible: status == Loader.Ready
                    }
                    
                    PowerNowP Offline
                    PowerNowP Offline
                    PowerNow
                    wrote on last edited by
                    #9

                    @KroMignon Hi, I just added asynchronous: true but surprisingly no change.

                    KroMignonK 1 Reply Last reply
                    0
                    • PowerNowP PowerNow

                      @KroMignon Hi, I just added asynchronous: true but surprisingly no change.

                      KroMignonK Offline
                      KroMignonK Offline
                      KroMignon
                      wrote on last edited by
                      #10

                      @PowerNow This sounds very strange to me. I often use asynchronous with Loader, and it always works.

                      Does your huge QML component also includes Loader?

                      It is an old maxim of mine that when you have excluded the impossible, whatever remains, however improbable, must be the truth. (Sherlock Holmes)

                      PowerNowP 1 Reply Last reply
                      0
                      • KroMignonK KroMignon

                        @PowerNow This sounds very strange to me. I often use asynchronous with Loader, and it always works.

                        Does your huge QML component also includes Loader?

                        PowerNowP Offline
                        PowerNowP Offline
                        PowerNow
                        wrote on last edited by
                        #11

                        @KroMignon The loaded Qml component "only" consists of a big QFramebufferObject which loads a lot of data in the graphiccard and this blocks the gui. Further Loader are not included.

                        T 1 Reply Last reply
                        0
                        • PowerNowP PowerNow

                          @KroMignon The loaded Qml component "only" consists of a big QFramebufferObject which loads a lot of data in the graphiccard and this blocks the gui. Further Loader are not included.

                          T Offline
                          T Offline
                          Tom_H
                          wrote on last edited by
                          #12

                          @PowerNow Then you are either doing something wrong or using a non-threaded render loop. By default there is a dedicated render thread and a dedicated main GUI thread. Loading of data to the graphics card should happen in the render thread and won't block the GUI.

                          Scene Graph and Rendering

                          PowerNowP 1 Reply Last reply
                          0
                          • T Tom_H

                            @PowerNow I solved a similar issue by using a Timer.

                            PowerNowP Offline
                            PowerNowP Offline
                            PowerNow
                            wrote on last edited by
                            #13

                            @Tom_H I tried it with a timer but it also does not work.

                            Timer {
                               id: iTim
                               interval: 0
                               running: false
                               repeat: false
                               triggeredOnStart: true
                               onTriggered: {
                                    console.log("onTriggered");
                                    iBut1.mTxt = "wait"
                                }
                            }
                            

                            Without triggeredOnStart: true the triggerSignal is fired after the heavyFunct() is finished.

                            1 Reply Last reply
                            0
                            • T Tom_H

                              @PowerNow Then you are either doing something wrong or using a non-threaded render loop. By default there is a dedicated render thread and a dedicated main GUI thread. Loading of data to the graphics card should happen in the render thread and won't block the GUI.

                              Scene Graph and Rendering

                              PowerNowP Offline
                              PowerNowP Offline
                              PowerNow
                              wrote on last edited by
                              #14

                              @Tom_H How can I found out that I'm using a non-threaded render loop? In the QQuickFrambufferObject I'm using of course the QQuickFramebufferObject::Renderer.

                              "Communication between the item and the renderer should primarily happen via the QQuickFramebufferObject::Renderer::synchronize() function. This function will be called on the render thread while the GUI thread is blocked."

                              It's still not clear how the gui and scene graph render works together. Based on the Qt arcticles it seems so that the scene graph render blocks the gui during rendering.

                              Is the gui blocked during upload of big Vertex/Index buffer objects?

                              1 Reply Last reply
                              0
                              • PowerNowP Offline
                                PowerNowP Offline
                                PowerNow
                                wrote on last edited by
                                #15

                                For who is interessted, I handle the problem by using the pressed() signal.

                                MouseArea  {
                                    property bool mRed: false
                                
                                    onClicked: {
                                       heavyFunct();
                                       mRed = false;
                                    }
                                    onPressed: {
                                       mRed = true;
                                    }
                                    onReleased: {
                                       mRed = false;
                                    }
                                }
                                
                                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