My Qt 4 application can only update the log box area (actually the whole GUI) until a function finishes execution. Is there any way to update the GUI/log box during the execution? Like adding something like QWidget::repaint() or QWidget::update() in the for loop, so the user can see that the GUI is processing, rather than wait until the function finishes and print out the log at once.
You need to occasionally call QCoreApplication::processEvents() during the execution of your function. This will keep the GUI alive and responsive by letting the event loop run.
An alternative is to execute your function in a separate thread. More information on threads in Qt can be found here: http://qt-project.org/doc/qt-4.8/threads.html.
Related
I have a Qwidget with a few tabs. In one of the tabs, after clicking a button, a function starts processing data and updates a progress bar.
I'd like to be able to change tabs while this process is running, currently it does'nt let me do so. Any idea?
(1) You must use a modeless progressdialog insteal of modal one. Practically, the main event loop must get the control to allow user interaction.
http://www.bogotobogo.com/Qt/Qt5_QProgressDialog_Modal_Modeless_QTimer.php
(2) You should put your data processing function to worker thread and invoke a progress dialog update to main UI thread from that. That way your task would not block UI, so you could interact with the window (like changing tab) meanwhile.
Qt also provides means to implement this, you might want to refer to:
QFuture, QtConcurrent::run(): run a task in separate thread.
QFutureWatcher: help monitor the progress of a task running in worker thread.
Example:
http://doc.qt.io/qt-5/qtconcurrent-progressdialog-example.html
Below logic may help you.
You can achieve this by using QThread.
Move the process to a separate thread(assume as worker thread)
So now there will be two thread (1. main thread & 2.worker thread)
Execute the process from worker thread
Use signal & slot mechanism to communicate between the main thread(1) & worker thread(2) (to update GUI and or to do some process)
This logic will stop the application from getting hanged.
Refer this link to know in detail.
You can get the sample application here, which follow the above said logic
Application screen shot :
Start Progress(Thread) : Start the thread and do process
Stop Process (Thread) : Stop the thread
Is there a way to detect whether execution is currently in the middle of QDialog.exec()?
I'm the author of DreamPie, a Python shell, and it lets you run Python code while Qt GUI is being displayed. It does that by running the Qt event loop for 1/10 of a second, and then checking if any Python commands need to be executed. The event loop is stopped by a QTimer which calls QApplication.quit() after the timeout.
If a QDialog.exec() is active, however, I don't want to call QApplication.quit(), because it will break the code. The current solution is to check whether there's a modal dialog active, by checking if QApplication.activeModalWidget() is None. However, I currently have a modal dialog which is not run with QDialog.exec(), and it's blocking Python commands for no reason.
Is there a way to exit the event loop only if it's not called recursively by QDialog.exec()?
Thanks!
You can check whether your dialog is visible with QDialog.isVisible. Normally, a modal dialog is visible only while it is being executed.
when using FlexPrintJob, after calling start(), a OS system print interface will appear, and at the same time Flex code execution will be paused, and it will remain paused until user finished interaction with the OS print dialog. the problem is I do have data from server, and the connection will time out within certain period, so is there any walk around to not pause the Flex code execution while OS print dialog is popped up. Thanks.
From the doc for FlexPrintJob:
You use the FlexPrintJob class to print a dynamically rendered document that you format specifically for printing.
This makes me wonder if you couldn't (essentially) fork off a second page from the browser that contains your print job and do the printing from there. This would leave your original page still running. In my flex apps I do this via PHP (create additional pages for printing and such). Example here.
Otherwise: you should finish all the server data d/l before starting the print job to avoid this issue.
Flex is only just recently starting to add multi-threading. It's adding worker threads of a sort but this won't help what you're asking for.
I am trying to add a gtkProgressBar to a little interface I created for an R script (using the RGtk2 package).
If I do something simple, as:
for (i in 1:50)
{
gtkProgressBarSetFraction(progress, i/50)
Sys.sleep(1)
}
everything runs smoothly and the bar is updated every second.
However, when I go to my actual code, I have a loop in which I do something like
for(i in 1:1000)
{
gtkProgressBarSetFraction(progress, i/1000)
#do some heavy computation here
}
The problem here is that the interface "freezes" and the progress bar is only updated at the end of the loop, therefore defeating completely its use...
Am I missing something here? How can I periodically "wake up" the interface so that it refreshes?
Thank you
nico
EDIT: OK, I solved the problem, but I still don't understand what is going on. I added a Sys.sleep call after the gtkProgressBarSetFraction and now the interface updates happily. To reduce "wasted time" I just did Sys.sleep(0.0001) (so for 1000 cycles I would only have ~0.1-1s more computing time, which is acceptable). Anyone could explain why is this happening?
To process one event: gtkMainIterationDo(FALSE). To process all pending events: while(gtkEventsPending()) gtkMainIteration().
This code is needed because of the way that the R and Gtk event loops interact - at every point, either R or Gtk is in control, and needs to manually hand off control to the other. Sys.sleep is one way of doing that, and these RGtk2 specific functions are another.
Almost all GUIs are made using concept called event loop. The program has some queue of messages and is itself infinitely looped in a process of picking new messages from the queue and executing them. The queue is populated by some events received from OS, like key strokes, mouse clicks, resizing windows, etc., and by the messages thrown by the program itself.
It doesn't seem like this, but R also has its own event loop (for graphics, but not only, and it is somewhat extended by RGtk, and while it is generally complicated I won't go into details).
Now when you call gtkProgressBarSetFraction, the progress bar is not directly updated, but a message requesting redraw is created and pushed to the queue. So, it makes no effect till it will be picked by the event loop iteration, but this won't happen until R will finish execution of your script OR when the loop will be fired exceptionally (by an internal timeout or by some functions, like Sys.sleep()).
I have an application which makes use of 20 different classes. The program execution starts in mainwindow. I start a progress dialog. I will make use of different classes for different purposes. After each function call which the execution goes to the particular class and does the required and come back to the mainwindow class, I will update the progress dialog. Now, the issue is the progress dialog freezes when the execution goes away from the mainwindow class. The cancel button is unable to accessed and so, the execution could not be stopped at the required time.
mainclass::mainclass()
{
ProgressDialog->exec();
x->add();
updateProgressDialog();
y->do();
updateProgressDialog();
zz->bring();
updateProgressDialog();
}
// x, y, z are three different classes.
This is how the execution goes. As soon as I enter the function in the main class, I will start the progress dialog. and call functions from different classes. The functions take considerable amount of time. I have invoked a thread to do the execution part, but I am unable to cancel the progress diaolog. I want the program execution to be stopped as and when the cancel button is pressed on the proggress dialog.
Please let me know how to get away with this issue. Hope I am clear here.
Without knowing exactly what calculations are being preformed in your threads its hard to isolate the problem. Maybe this can help: Keeping the GUI Responsive
Excerpt from: Performing Long Operations (by: Witold Wysota)
During long calculations (regardless of any usage of signals and slots) all event processing gets halted. As a result, the GUI is not refreshed, user input is not processed, network activity stops and timers don't fireāthe application looks like it's frozen and, in fact, the part of it not related to the time-intensive task is frozen.
The functions you are calling are not processing the Qt events loop. You are using a modal progress bar, since you are calling exec(). This means that Qt only gets control at the times where you update the dialog.
The only way that I know of to work around this is to code the dialog as modeless, but you will also have to provide an opportunity for the events loop to process.
This is explained in a fair amount of detail in the Qt docs: QProgressDialog