Re: [Interest] QProgressDialog not showing processEvents()
On Monday, November 18, 2013 08:09:41 AM André Somers wrote: It is *not* called by setValue. That is a Good Thing(TM). I strongly encourage reading code or documentation before making such answers... \warning If the progress dialog is modal (see QProgressDialog::QProgressDialog()), setValue() calls QApplication::processEvents(), so take care that this does not cause undesirable re-entrancy in your code. For example, don't use a QProgressDialog inside a paintEvent()! void QProgressDialog::setValue(int progress) { Q_D(QProgressDialog); if (progress == d-bar-value() || (d-bar-value() == -1 progress == d-bar-maximum())) return; d-bar-setValue(progress); if (d-shown_once) { if (isModal()) QApplication::processEvents(); } else { [...] } This is not a bug however, it's the expected use case for QProgressDialog. The usually-very-dangerous processEvents() is only midly dangerous because we are protected by the progress dialog, i.e. the user cannot close the mainwindow, for instance. But of course, timers and sockets could still trigger code that deletes objects etc. In any case - to come back to the initial question: did you call setValue(0) upfront? I just pushed a review request for this to happen automatically, but it's not merged yet. https://codereview.qt-project.org/71619 -- David Faure | david.fa...@kdab.com | Managing Director KDAB France KDAB (France) S.A.S., a KDAB Group company Tel. France +33 (0)4 90 84 08 53, Sweden (HQ) +46-563-540090 KDAB - Qt Experts - Platform-independent software solutions ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QProgressDialog not showing processEvents()
David Faure schreef op 20-11-2013 12:30: On Monday, November 18, 2013 08:09:41 AM André Somers wrote: It is *not* called by setValue. That is a Good Thing(TM). I strongly encourage reading code or documentation before making such answers... Oops... /me goes to hide quietly in a corner and be ashamed of himself André ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QProgressDialog not showing processEvents()
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 ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QProgressDialog not showing processEvents()
Bo Thorsen schreef op 18-11-2013 9:27: 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. To me, it really depends how easy splitting the work in chunks is going to be. Without knowing what is being saved, there is no way to know. Threading is indeed difficult to debug, but if used localized in the right way is also not *that* hard to manage. The big benefit is that the actual saving stays localized in a single simple function. Using the chunks method will spread it around. You'll end up with local variables, flags, etc. That might be easier, or it might be harder. It depends on the situation. That's why I mentioned both approaches in my reply. We actually _do_ use threading for asynchronous I/O in our application, and that works rather nicely. André ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QProgressDialog not showing processEvents()
Etienne Sandré-Chardonnal schreef op 15-11-2013 14:05: Dear all, I have a long file saving function (gigabytes - several minutes) and I am trying to use QProcessDialog. I am using it the Modal way as explained in the documentation. However, the dialog appears after about 50 seconds, despite having set the minimumDuration to 0, and called setValue() several times before. Googling for the issue says I need to call QApplication::processEvents regularly in order for the GUI to refresh. However, the doc says : If the progress dialog is modal (seeQProgressDialog::QProgressDialog qthelp://com.trolltech.qt.481/qdoc/qprogressdialog.html#QProgressDialog()), setValue() callsQApplication::processEvents qthelp://com.trolltech.qt.481/qdoc/qcoreapplication.html#processEvents(), so take care that this does not cause undesirable re-entrancy in your code So I'm puzzled... Do I need to call it, or is it already called by setValue? In the example there are no explicit calls to processEvents(). Qt 4.8.1 It is *not* called by setValue. That is a Good Thing(TM). In fact, I think the whole call is dangerous to begin with. 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. Note that this does not only go for saving or loading, but it goes for any task that may block your GUI thread for a substantial amount of time. André ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QProgressDialog not showing processEvents()
Hi, it is always safe to call processEvents yourself. If the QProgressDialog has display issues it obviously does not get enough CPU to update itself, calling processEvents more often may(!!) help. When I want to see a QProgressDialog early I normally force the issue by calling show() immediately. That's more reliable than leaving it to the internal heuristics. Especially if there may be a long time before the first call to processEvents. If you are just copying a lot of data it may be a good idea to do this in a separate thread and just throw the updates (Qt::QueuedConnection!) to the GUI thread from time to time. This way the GUI remains fully intact. (Hint: if you delete objects during saving: use deleteLater; if you allocate new stuff do it in a slot with BlockingQueuedConnection or use moveToThread). Konrad On Friday, Friday 15 November 2013 at 14:05, Etienne Sandré-Chardonnal wrote: Dear all, I have a long file saving function (gigabytes - several minutes) and I am trying to use QProcessDialog. I am using it the Modal way as explained in the documentation. However, the dialog appears after about 50 seconds, despite having set the minimumDuration to 0, and called setValue() several times before. Googling for the issue says I need to call QApplication::processEvents regularly in order for the GUI to refresh. However, the doc says : If the progress dialog is modal (seeQProgressDialog::QProgressDialogqthelp://com.trolltech.qt.481/qdoc/qpr ogressdialog.html#QProgressDialog()), setValue() callsQApplication::processEventsqthelp://com.trolltech.qt.481/qdoc/qcorea pplication.html#processEvents(), so take care that this does not cause undesirable re-entrancy in your code So I'm puzzled... Do I need to call it, or is it already called by setValue? In the example there are no explicit calls to processEvents(). Qt 4.8.1 Thanks! Etienne signature.asc Description: This is a digitally signed message part. ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QProgressDialog not showing processEvents()
On segunda-feira, 18 de novembro de 2013 08:15:48, Konrad Rosenbaum wrote: it is always safe to call processEvents yourself. No, it's not. There are a lot of situations when doing that will cause you problems elsewhere. -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel Open Source Technology Center signature.asc Description: This is a digitally signed message part. ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest
Re: [Interest] QProgressDialog not showing processEvents()
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. HTH, -mandeep ___ Interest mailing list Interest@qt-project.org http://lists.qt-project.org/mailman/listinfo/interest