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. Why isn't my repaint() shown?
Forum Updated to NodeBB v4.3 + New Features

Why isn't my repaint() shown?

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 99 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.
  • PerdrixP Offline
    PerdrixP Offline
    Perdrix
    wrote last edited by SGaist
    #1

    I've got some code in my QDialog sub-class that is triggered when a QFuture finishes:

    
    		connect(this, &QualityChart::showEccentricity,
    			this, &QualityChart::plotEccentricity, Qt::QueuedConnection);
    		connect(this, &QualityChart::showFWHM,
    			this, &QualityChart::plotFWHM, Qt::QueuedConnection);
    
    void QualityChart::interpolationFinished()
    {
    	interpolating = false;
    	progressBar->reset();
    	message->setText(tr("Calculating contour plot.  Please be patient."));
            update();
    	QCoreApplication::processEvents();
    
    	if (!cancelled)
    	{
    		ZTRACE_RUNTIME("Interpolation complete");
    		//
    		// Show the appropriate chart
    		//
    		if (radioEccentricity->isChecked())
    		{
    			QTimer::singleShot(100,
    				[this]()
    				{
    					emit showEccentricity();
    				});
    		}
    		else
    		{
    			QTimer::singleShot(100,
    				[this]()
    				{
    					emit showFWHM();
    				});
    
    		}
    	}
    	else
    	{
    		ZTRACE_RUNTIME("Interpolation cancelled");
    		reject();
    	}
    }
    

    I was expecting the update to the message and the progress bar to be handled before the moderately slow code connected to the emitted signals was run, but that's not what happens, the results of (e.g. plotEccentricity() are displayed and the message update and progress bar update only happen then.

    I thought that by invoking e.g. plotEccentricity using a single shot would allow the update to be proceessed but clearly not.

    What am I missing here?

    Thanks David

    jsulmJ 1 Reply Last reply
    0
    • PerdrixP Perdrix

      I've got some code in my QDialog sub-class that is triggered when a QFuture finishes:

      
      		connect(this, &QualityChart::showEccentricity,
      			this, &QualityChart::plotEccentricity, Qt::QueuedConnection);
      		connect(this, &QualityChart::showFWHM,
      			this, &QualityChart::plotFWHM, Qt::QueuedConnection);
      
      void QualityChart::interpolationFinished()
      {
      	interpolating = false;
      	progressBar->reset();
      	message->setText(tr("Calculating contour plot.  Please be patient."));
              update();
      	QCoreApplication::processEvents();
      
      	if (!cancelled)
      	{
      		ZTRACE_RUNTIME("Interpolation complete");
      		//
      		// Show the appropriate chart
      		//
      		if (radioEccentricity->isChecked())
      		{
      			QTimer::singleShot(100,
      				[this]()
      				{
      					emit showEccentricity();
      				});
      		}
      		else
      		{
      			QTimer::singleShot(100,
      				[this]()
      				{
      					emit showFWHM();
      				});
      
      		}
      	}
      	else
      	{
      		ZTRACE_RUNTIME("Interpolation cancelled");
      		reject();
      	}
      }
      

      I was expecting the update to the message and the progress bar to be handled before the moderately slow code connected to the emitted signals was run, but that's not what happens, the results of (e.g. plotEccentricity() are displayed and the message update and progress bar update only happen then.

      I thought that by invoking e.g. plotEccentricity using a single shot would allow the update to be proceessed but clearly not.

      What am I missing here?

      Thanks David

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote last edited by
      #2

      @Perdrix You should not block the Qt event loop. Using processEvents() is a dirty work around which may or may not work. Move long running calculations into a thread.

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      Christian EhrlicherC 1 Reply Last reply
      1
      • jsulmJ jsulm

        @Perdrix You should not block the Qt event loop. Using processEvents() is a dirty work around which may or may not work. Move long running calculations into a thread.

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

        @jsulm https://forum.qt.io/topic/163776/

        He does not care

        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
        • PerdrixP Offline
          PerdrixP Offline
          Perdrix
          wrote last edited by
          #4

          I do very much care, but found that I can't move the invocation of QwtPlot::replot() into a thread. I tried.

          JonBJ 1 Reply Last reply
          0
          • PerdrixP Perdrix

            I do very much care, but found that I can't move the invocation of QwtPlot::replot() into a thread. I tried.

            JonBJ Online
            JonBJ Online
            JonB
            wrote last edited by JonB
            #5

            @Perdrix
            I don't know the details of your situation. However, I assume QwtPlot::replot() causes a UI update. The Qt rule is: you must not attempt to update the UI from any secondary thread, only the main one.

            What you are supposed to do is move all calculations to a secondary thread. Then maybe have that emit a signal when done. At that point the main thread has a slot on that and does any updates or repaints. The intention is that time consuming calculations are removed from the main thread, hopefully making it "smoother", though the redraw has to be from main. Is that what you are doing?

            1 Reply Last reply
            0
            • PerdrixP Offline
              PerdrixP Offline
              Perdrix
              wrote last edited by Perdrix
              #6

              Sure, I totally get that, and I've done precisely that for the interpolation code. But QwtPlot::replot() is not in my control and does block the event loop (it uses QFuture::waitForFinished() rather than using a QFutureWatcher and handling the finished signal).

              JonBJ 1 Reply Last reply
              1
              • PerdrixP Perdrix

                Sure, I totally get that, and I've done precisely that for the interpolation code. But QwtPlot::replot() is not in my control and does block the event loop (it uses QFuture::waitForFinished() rather than using a QFutureWatcher and handling the finished signal).

                JonBJ Online
                JonBJ Online
                JonB
                wrote last edited by JonB
                #7

                @Perdrix
                Good that you know about UI and threads. I don't get the stuff about QwtPlot::replot() and it using QFuture::waitForFinished(), I don't see evidence for that. Nor do I see where you call it in your code. Unless you mean there is a call to it elsewhere in your own project, and that uses waitForFinished()? In which case you may need to alter that code? That's all I know.

                1 Reply Last reply
                0
                • PerdrixP Offline
                  PerdrixP Offline
                  Perdrix
                  wrote last edited by
                  #8

                  As I said Qwt isn't in my control. It's an external library. The code that was connected to showXXXX signals called QwtPlot::replot.

                  JonBJ 1 Reply Last reply
                  0
                  • PerdrixP Perdrix

                    As I said Qwt isn't in my control. It's an external library. The code that was connected to showXXXX signals called QwtPlot::replot.

                    JonBJ Online
                    JonBJ Online
                    JonB
                    wrote last edited by
                    #9

                    @Perdrix
                    I get that but you wrote

                    But QwtPlot::replot() is not in my control and does block the event loop (it uses QFuture::waitForFinished() rather than using a QFutureWatcher and handling the finished signal).

                    I don't get the QFuture part, you haven't explained. What uses "QFuture::waitForFinished() rather than ..."? The code of QwtPlot::replot() from Qwt people? I don't see that. Code in an external library calls QwtPlot::replot() and also has its own QFuture::waitForFinished(), is that what you are saying? I don't know, to me it's most unclear.

                    1 Reply Last reply
                    0
                    • PerdrixP Offline
                      PerdrixP Offline
                      Perdrix
                      wrote last edited by
                      #10

                      QwtPlot::replot() is part of the Qwt library which I am using. For a spectrogram plot that eventually calls QwtPlotRasterItem::compose() which does:

                             QVector< QFuture< void > > futures;
                             futures.reserve( numThreads - 1 );
                      
                             for ( uint i = 0; i < numThreads; i++ )
                             {
                                 QRect tile( 0, i * numRows, image.width(), numRows );
                                 if ( i == numThreads - 1 )
                                 {
                                     tile.setHeight( image.height() - i * numRows );
                                     qwtToRgba( &image, &alphaImage, tile, m_data->alpha );
                                 }
                                 else
                                 {
                                     futures += QtConcurrent::run(
                                         &qwtToRgba, &image, &alphaImage, tile, m_data->alpha );
                                 }
                             }
                             for ( int i = 0; i < futures.size(); i++ )
                                 futures[i].waitForFinished();
                      

                      which completely blocks the Qt event loop until it finishes.

                      JonBJ 1 Reply Last reply
                      1
                      • PerdrixP Perdrix

                        QwtPlot::replot() is part of the Qwt library which I am using. For a spectrogram plot that eventually calls QwtPlotRasterItem::compose() which does:

                               QVector< QFuture< void > > futures;
                               futures.reserve( numThreads - 1 );
                        
                               for ( uint i = 0; i < numThreads; i++ )
                               {
                                   QRect tile( 0, i * numRows, image.width(), numRows );
                                   if ( i == numThreads - 1 )
                                   {
                                       tile.setHeight( image.height() - i * numRows );
                                       qwtToRgba( &image, &alphaImage, tile, m_data->alpha );
                                   }
                                   else
                                   {
                                       futures += QtConcurrent::run(
                                           &qwtToRgba, &image, &alphaImage, tile, m_data->alpha );
                                   }
                               }
                               for ( int i = 0; i < futures.size(); i++ )
                                   futures[i].waitForFinished();
                        

                        which completely blocks the Qt event loop until it finishes.

                        JonBJ Online
                        JonBJ Online
                        JonB
                        wrote last edited by
                        #11

                        @Perdrix Fair enough, I had not understood there was such in Qwt code.

                        1 Reply Last reply
                        0
                        • PerdrixP Offline
                          PerdrixP Offline
                          Perdrix
                          wrote last edited by
                          #12
                          This post is deleted!
                          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