[SOLVED] Displaying progress messages with QTextEdit
-
If you use, for instance, a QTimer::singleShot(...) with a timeout of 0, it will call the given slot as soon as it can on the event loop. It's kind of a short cut to saying "process your events that are pending, and then call this slot as soon as possible. It's not better or worse, necessarily, just another option.
Off the top of my head, I wouldn't think that you would need to do anything to manually refresh the QTextEdit, so I'm a little unsure of what to tell you.
Can you provide a minimal code example of how you're splitting things up and how you're working with setting and updating the QTextEdit?
-
The fact that you did not use a timer (and I assume, also not another method of returning to the event loop) and the fact that you need something like show on the widget to make it update, I think your changes did not reach the target of the whole excersise of breaking up your operation in small chunks yet. The whole point is, that you give your application the opportunity to return to the event loop regulary. The application needs that to stay responsive: to be able to respond to mouse and keyboard operations, to do updates to widgets, to redraw areas that may have become covered and uncovered in the meantime, etc. An application that does not return to the eventloop frequently enough feels unresponsive to a user.
By using a QTimer as suggested by mlong, you make sure that after each chunk of your process, you give the Qt machinery the opportunity to do its work. After that, your process will continue. That will also ensure that your QTextEdit will just display the updates you make to its text, without you having to call show() on it.
-
The point why the refresh without doing anything does not work is, that you need the repainting stuff, which needs a return to the event loop. I would not use show() to force repainting, I would use repaint() :-) to force it now, but from my POV that's no good design to need that.
If you have longer running stuff to do, there are IMHO two options:
- breaking it up like mlong suggested into several steps and doing one part and then (at the end) do a single shot timer or a queued message call to reenter the stuff from the event loop
- moving the long time operation to a seperate thread ( "look at peppes article":http://developer.qt.nokia.com/wiki/Threads_Events_QObjects ).
-
Thank you all for taking the time to respond to my questions. Unfortunately, I still don't think I've achieved the goal. Below is an outline of my code:
@FileProcessingDialog::FileProcessingDialog(QDialog *parent) {
setupUi(this);
QTimer::singleShot(0, this, SLOT(part1()));
}
void FileProcessingDialog::part1() {
......do stuff
textEdit_updates->append("Hello1);
QTimer::singleShot (0, this, SLOT(part2()));
}
void FileProcessingDialog::part2() {
.....do stuff
textEdit_updates->append("Hello2);
QTimer::singleShot(0, this, SLOT(part3()));
}
...etc.
@I'm not sure if I put the "textEdit_updates->append()" statements in the right place. Do they belong in the slot bodies or in the FileProcessingDialog constructor? Presently, the QTextEdit does not display the messages quickly.
Again, I really appreciate your helpful responses. -
I doubt that this is actual code, right?
How much work is performed in each of your steps?
-
...this is actually the basic structure of my code. Is there something fundamentally wrong? Please let me know!!
As for the work done in each slot, it can potentially take several seconds. I would like the QTextEdit to reflect the progress of the functions by displaying messages. Presently, I would consider the user experience minimally acceptable, but it could definitely be better.
-
The "do stuff" parts are the real issue -- what are you doing in there? Can you split that work in smaller chunks? Can you offload it to another thread?
-
The "do stuff" chunks perform some pretty heavy computations, and I've already broken the original code into 6 chunks. Could you please tell whether the code I posted above is correctly implementing the procedure as originally recommended by mlong?
His suggestion was:
"You can break your function up into a series of parts and periodically call one or more slots with a QTimer to do the next part."
Am I still missing the point?
Thanks in advance. -
No, the point is there, but ideally every part should take no more than some milliseconds to not be noticeable by the user. If your computations are heavy and you can't break them in an easy way (and/or add calls to processEvents) move them to another thread or process.
-
I implemented a separate thread and the user experience is much improved.
Thanks so much for everyone's guidance and helpful suggestions! -
Glad to see it's working!