Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QProgressDialog does not take input unless the progress value changes
Forum Updated to NodeBB v4.3 + New Features

QProgressDialog does not take input unless the progress value changes

Scheduled Pinned Locked Moved Unsolved General and Desktop
14 Posts 6 Posters 794 Views 2 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.
  • J Offline
    J Offline
    JanLaloux
    wrote on last edited by
    #1

    I have a classic QProgressDialog and while the processing proceeds the method "wasCanceled()" is regularly called to check if the user pressed the Cancel button. This works, but as long as the progress value is not changed the Clear button is completly unreactive. You can click on it but wasCanceled() will return false. Only when the progress value changes the click on the button is captured. Unfortunately, in this case it is not possible to increasing the update of the progress value.

    I tried this when checking for cancelation:

    progress->setValue( progress->value() ); 
    canceled = progress->wasCanceled();
    

    but that does not help, still got false as return value.

    My fix for the moment is:

    int value = progress->value();
    progress->setValue( value+1 );
    progress->setValue( value );
    canceled = progress->wasCanceled();
    

    and this works. But this is ugly of course.
    Is there another solution to this?

    JonBJ andrewmorganA 2 Replies Last reply
    1
    • J JanLaloux

      I have a classic QProgressDialog and while the processing proceeds the method "wasCanceled()" is regularly called to check if the user pressed the Cancel button. This works, but as long as the progress value is not changed the Clear button is completly unreactive. You can click on it but wasCanceled() will return false. Only when the progress value changes the click on the button is captured. Unfortunately, in this case it is not possible to increasing the update of the progress value.

      I tried this when checking for cancelation:

      progress->setValue( progress->value() ); 
      canceled = progress->wasCanceled();
      

      but that does not help, still got false as return value.

      My fix for the moment is:

      int value = progress->value();
      progress->setValue( value+1 );
      progress->setValue( value );
      canceled = progress->wasCanceled();
      

      and this works. But this is ugly of course.
      Is there another solution to this?

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @JanLaloux
      I'm not really with you, but if you are periodically "polling" wasCanceled(), you should not be, you should be connected to the canceled() signal? So if you use that does it work?

      1 Reply Last reply
      0
      • J Offline
        J Offline
        JanLaloux
        wrote on last edited by
        #3

        No, same problem.
        But what's wrong with calling wasCancelled()? Docs: "This property holds whether the dialog was canceled"
        Forgot to tell: Qt 6.5.2 for C++ on Windows

        JonBJ 1 Reply Last reply
        0
        • J JanLaloux

          No, same problem.
          But what's wrong with calling wasCancelled()? Docs: "This property holds whether the dialog was canceled"
          Forgot to tell: Qt 6.5.2 for C++ on Windows

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @JanLaloux
          The question is when it gets set. Did you try the signal to see whether it works in your situation, then you would know whether that is the issue?

          1 Reply Last reply
          0
          • Christian EhrlicherC Online
            Christian EhrlicherC Online
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            When you block the event loop - how should the ui be redrawn? Use the canceld() signal and don't block the event loop...

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            3
            • S Offline
              S Offline
              SimonSchroeder
              wrote on last edited by
              #6

              At some point the mouse events need to be processed. For this the event loop needs to run. It is very likely that you are blocking the event loop. There might be some weird behavior when calling setValue with a different progress that uses some direct connection to update the progress bar and also somehow processes the mouse event.

              As a quick test you can call QApplication::processEvents() right before your call to wasCanceled() to see if this solves your problem. If it does you are definitely blocking the event loop. However, don't use this trick as your final solution. Your current loop will take about 100 times longer if you do this. It is not worth to slow down your actual processing by 100x just to have a nice UI.

              Instead, then your solution should be to use a separate worker thread. You are not allowed to call any UI functions from the worker thread: no call to wasCanceled and no call to setValue. Instead you need to use signals and slots to connect these function calls.

              1 Reply Last reply
              1
              • J JanLaloux

                I have a classic QProgressDialog and while the processing proceeds the method "wasCanceled()" is regularly called to check if the user pressed the Cancel button. This works, but as long as the progress value is not changed the Clear button is completly unreactive. You can click on it but wasCanceled() will return false. Only when the progress value changes the click on the button is captured. Unfortunately, in this case it is not possible to increasing the update of the progress value.

                I tried this when checking for cancelation:

                progress->setValue( progress->value() ); 
                canceled = progress->wasCanceled();
                

                but that does not help, still got false as return value.

                My fix for the moment is:

                int value = progress->value();
                progress->setValue( value+1 );
                progress->setValue( value );
                canceled = progress->wasCanceled();
                

                and this works. But this is ugly of course.
                Is there another solution to this?

                andrewmorganA Offline
                andrewmorganA Offline
                andrewmorgan
                wrote on last edited by
                #7

                @JanLaloux You’re right! Manually incrementing and resetting the progress value is not ideal. A cleaner approach could be calling QCoreApplication::processEvents() inside your loop to allow UI events (like button clicks) to be processed without artificially changing the progress value. You might also try setAutoReset(false) or setMinimumDuration(0) to see if it improves responsiveness.

                JonBJ 1 Reply Last reply
                0
                • andrewmorganA andrewmorgan

                  @JanLaloux You’re right! Manually incrementing and resetting the progress value is not ideal. A cleaner approach could be calling QCoreApplication::processEvents() inside your loop to allow UI events (like button clicks) to be processed without artificially changing the progress value. You might also try setAutoReset(false) or setMinimumDuration(0) to see if it improves responsiveness.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #8

                  @andrewmorgan
                  It would not be ideal to call processEvents(). It would be better to allow the main event loop to run and raise and act on the canceled() signal, as previously written.

                  Pl45m4P 1 Reply Last reply
                  2
                  • J Offline
                    J Offline
                    JanLaloux
                    wrote on last edited by
                    #9

                    Thanks all for the valuable input!

                    @SimonSchroeder: the test with QApplication::processEvents() is positive, the problem goes away.
                    BUT: the implementation is as documented for the QProgressDialog Class for the modal operation:
                    "Compared to a modeless QProgressDialog, a modal QProgressDialog is simpler to use for the programmer. Do the operation in a loop, call setValue() at intervals, and check for cancellation with wasCanceled(). "
                    So with the functions, not the signals.
                    And since it is the intention that the user cannot do anything than either wait for the operation to finish, or to cancel it, this seems to me correct for the modal operation?

                    Christian EhrlicherC 1 Reply Last reply
                    0
                    • JonBJ JonB

                      @andrewmorgan
                      It would not be ideal to call processEvents(). It would be better to allow the main event loop to run and raise and act on the canceled() signal, as previously written.

                      Pl45m4P Offline
                      Pl45m4P Offline
                      Pl45m4
                      wrote on last edited by
                      #10

                      @JonB said in QProgressDialog does not take input unless the progress value changes:

                      It would not be ideal to call processEvents()

                      The only valid use case for processEvent() to update the progress of QProgressDialog/ QProgressBar is when using it in combination with tasks that run in main.cpp before the event loop is even started or like everything QSplashScreen related...


                      If debugging is the process of removing software bugs, then programming must be the process of putting them in.

                      ~E. W. Dijkstra

                      1 Reply Last reply
                      0
                      • J JanLaloux

                        Thanks all for the valuable input!

                        @SimonSchroeder: the test with QApplication::processEvents() is positive, the problem goes away.
                        BUT: the implementation is as documented for the QProgressDialog Class for the modal operation:
                        "Compared to a modeless QProgressDialog, a modal QProgressDialog is simpler to use for the programmer. Do the operation in a loop, call setValue() at intervals, and check for cancellation with wasCanceled(). "
                        So with the functions, not the signals.
                        And since it is the intention that the user cannot do anything than either wait for the operation to finish, or to cancel it, this seems to me correct for the modal operation?

                        Christian EhrlicherC Online
                        Christian EhrlicherC Online
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        @JanLaloux said in QProgressDialog does not take input unless the progress value changes:

                        Compared to a modeless QProgressDialog, a modal QProgressDialog is simpler to use for the programmer. Do the operation in a loop, call setValue() at intervals, and check for cancellation with wasCanceled(). "
                        So with the functions, not the signals.

                        We should adjust the documentation... blocking the event loop is a bad idea.

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        1 Reply Last reply
                        0
                        • S Offline
                          S Offline
                          SimonSchroeder
                          wrote on last edited by
                          #12

                          Usually you'll see a pulsing inside the progress bar. If you depend on calling setValue this will not be smooth. It'll always look like your application is hanging. And if you call setValue too often (i.e. often enough for the progress bar to be smooth) it will significantly slow down your actual work. Also, in the former case Windows might report "Not responding" (especially when clicking "Cancel").

                          We were looking for an easy solution (in our case to just do little changes to our existing code) to fix this problem. What we came up with you can find here: https://github.com/SimonSchroeder/QtThreadHelper. It's a simple header-only library where you can easily create a worker thread using just a lambda and a helper function guiThread to just call setValue inside the GUI thread right from your worker thread. You should still connect the canceled signal to react to this.

                          JonBJ 1 Reply Last reply
                          2
                          • S SimonSchroeder

                            Usually you'll see a pulsing inside the progress bar. If you depend on calling setValue this will not be smooth. It'll always look like your application is hanging. And if you call setValue too often (i.e. often enough for the progress bar to be smooth) it will significantly slow down your actual work. Also, in the former case Windows might report "Not responding" (especially when clicking "Cancel").

                            We were looking for an easy solution (in our case to just do little changes to our existing code) to fix this problem. What we came up with you can find here: https://github.com/SimonSchroeder/QtThreadHelper. It's a simple header-only library where you can easily create a worker thread using just a lambda and a helper function guiThread to just call setValue inside the GUI thread right from your worker thread. You should still connect the canceled signal to react to this.

                            JonBJ Offline
                            JonBJ Offline
                            JonB
                            wrote on last edited by
                            #13

                            @SimonSchroeder
                            All very impressive! Nicely written up --- does your company give you time to write that up and publish it, or did you do that in your own time?

                            S 1 Reply Last reply
                            0
                            • JonBJ JonB

                              @SimonSchroeder
                              All very impressive! Nicely written up --- does your company give you time to write that up and publish it, or did you do that in your own time?

                              S Offline
                              S Offline
                              SimonSchroeder
                              wrote on last edited by
                              #14

                              @JonB, thank you! It does not happen very often, but this I could write on company time. We need the documentation anyways.

                              1 Reply Last reply
                              1

                              • Login

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