[Interest] QProgressDialog not showing & processEvents()

Bo Thorsen bthorsen at ics.com
Mon Nov 18 09:27:35 CET 2013


Den 18-11-2013 08:59, Mandeep Sandhu skrev:
>> You have two viable approaches here:
>> * break up the saving method into chunks. That is, do a small part of the
>> work of the saving, queue the next piece of work to be done, and return to
>> the eventloop. The eventloop will then trigger the next queued piece of the
>> work being done. This way, there is no need for processEvents() at all.
>> * move your saving code to a worker object, and execute it in a separate
>> thread. Also, no need to use processEvents, as the heavy lifting is done
>> outside of the GUI thread.
>
> I'd too suggest the separate thread method as it's more generic and
> will across different scenario's.
>
> The only thing that you need to worry about is that your thread's
> actions are in sync with what the GUI is showing. Eg: in case you
> provide a cancel button, you'll have to inform the worker thread to
> abort and wait for it to exit cleanly.

I strongly object to using a thread for something this simple. Threading 
is to be avoided whenever possible, because it's so hard to debug. Use 
the chunks method instead. Something like this:

class FileLoader : public QObject {
   Q_OBJECT

public:
   explicit FileLoader(const QString& fileName) {
     m_file(fileName);
     m_timer.setSingleShot(false);
     m_timer.setInterval(0);
     m_timer.start();
     connect(&m_timer, SIGNAL(triggered()), SLOT(readChunk()));

     m_file.open(QIODevice::ReadOnly));
   }

signals:
   void done(const QByteArray& bytes);
   void failed();
   void progress(qreal percent);

private slots:
   void readChunk() {
     if (!m_file.isOpen()) {
       m_timer.stop();
       emit failed();
     } else {
       m_bytes.append(m_file.read(1024));
       if (m_bytes.size() == m_file.size()) {
         m_timer.stop();
         emit done(m_bytes);
       } else {
         emit progress(100.0 * m_bytes.size() / m_file.size());
       }
     }
   }

private:
   QFile m_file;
   QTimer m_timer;
   QByteArray m_bytes;
};

This was written from memory, don't take it as real code. You can also 
consider QBuffer and other things. It's not the purpose here to show 
loading of the file.

The point with this is to use the timer to allow the rest of the system 
to keep doing everything it should, while the file is loading. Now the 
progressbar has the time it needs to show the updates.

This technique is important for Qt people. Chunks with timers is a 
standard way of avoiding threads. When threads are necessary, so be it. 
But don't introduce them when this could be done instead.

Bo.

-- 
Bo Thorsen, European Engineering Manager, ICS
Integrated Computer Solutions. Delivering World-Class Applications
http://ics.com/services



More information about the Interest mailing list