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()).
Related
I have a small IDE for a modeling language I wrote, implemented in PyQt/PySide, and am trying to implement a code navigator that let's you jump to different sections in the file being edited.
The current implementation is: (1) connect to QPlainTextEditor.textChanged, (2) any time a change is made, (sloppily) parse the file and update the navigator pane
It seems to work OK, but I'm worried this could cause major performance issues for large files on slower systems, in particular if more stuff is connected to textChanged in the future.
My question: Has anybody here implemented a delayed reaction to events, so that multiple events (i.e. keystrokes) within a short period only trigger a single update (say once per second)? And is there a proper QT way of doing this?
Thanks,
Michael
You can try using timers if you want some "delay".
There would be 2 ways to use them (with different results).
One is only parse after no input has been done for a certain amount of time
NOTE: I only know C++ Qt but I assume the same things are valid for pyqt so this is kind of "pseudocode" I hope you get the concept though.
QTimer timer; //somewhere
timer.setSingleShot(true); //only fire once
connect(timer,QTimer::timeout(),OnTimerDone(...);
OnTextChanged(...)
{
timer.start(500); //wait 500ms
}
OnTimerDone(...)
{
DoStuff(...);
}
This will restart the timer every input, so when you call that and the timer is not done the timeout signal is not emitted. When no input is done for an amount of time the timer timeouts and you parse the file.
The second option would be to have a periodic timer running (singleShot(false)).
Just start the timer for like each second. and timeout will be called once a second. You can combine that with a variable which you set to true when the input changes and to false when the file is parsed. So you avoid parsing when nothing has changed.
In C++Qt you won't have to worry about multi-threading because the slot gets called in the GUI thread. I assume it is the same for python but you should probably check this.
I'm currently writing a macro that performs a series of control sends and control clicks.
They must be done in the exact order.
At first I didn't have any sleep statements, so the script would just go through each command regardless whether the previous has finished or not (ie: click SUBMIT before finish sending the input string)
So I thought maybe I'll just put some sleep statements, but then I have to figure out how best to optimize it, AND I have to consider whether others' computers' speeds because a slow computer would need to have longer delays between commands. That would be impossible to optimize for everyone.
I was hoping there was a way to force each line to be run only after the previous has finished?
EDIT: To be more specific, I want the controlsend command to finish executing before I click the buttons.
Instead of ControlSend, use ControlSetText. This is immediate (like GuiEdit).
My solution: use functions from the user-defined library "GuiEdit" to directly set the value of the textbox. It appears to be immediate, thus allowing me to avoid having to wait for the keystrokes to be sent.
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
From hard experience I've found it useful to occasionally save the state of my long computations to disk to start them up later if something fails. Can I do this in a distributed computation package in R (like SNOW or multicore)?
It does not seem clear how this could be done since the master is collecting things from the slaves in a non-transparent way.
This is (again :-) a hard one.
You could try to dump snapshots on the nodes using save() or save.image(). You could then try to re-organize your code so that the nodes can resume after the last snapshot.
Or you could try to re-organize your workflow such that nodes 'take tickets' and return the results. That way the central node keeps tabs on everything and you can log interim results there.
Either way, what you desire is not available out of the box (as far as I know).
I have been involved in building a custum QGIS application in which live data is to be shown on the viewer of the application.
The IPC being used is unix message queues.
The data is to be refreshed at a specified interval say, 3 seconds.
Now the problem that i am facing is that the processing of the data which is to be shown is taking more than 3 seconds,so what i have done is that before the app starts to process data for the next update,the refresh QTimer is stopped and after the data is processed i again restart the QTimer.The app should work in such a way that after an update/refresh(during this refresh the app goes unresponsive) the user should get ample time to continue to work on the app apart from seeing the data being updated.I am able to get acceptable pauses for the user to work-- in one scenario.
But on different OS(RHEL 5.0 to RHEL 5.2) the situation is something different.The timer goes wild and continues to fire without giving any pauses b/w the successive updates thus going into an infinite loop.Handling this update data definitely takes longer than 3 sec,but for that very reason i have stopped-restarted the timer while processing..and the same logic works in one scenario while in other it doesnt.. The other fact that i have observed is that when this quick firing of the timer happens the time taken by the refreshing function to exit is very small abt 300ms so the start-stop of the timer that i have placed at the start-and-end of this function happens in that small time..so before the actual processing of the data finishes,there are 3-4 starts of the timer in queue waiting to be executed and thus the infinite looping problem gets worse from that point for every successive update.
The important thing to note here is that for the same code in one OS the refresh time is shown to be as around 4000ms(the actual processing time taken for the same amount of data) while for the other OS its 300ms.
Maybe this has something to do with newer libs on the updated OS..but I dont know how to debug it because i am not able to get any clues why its happening as such... maybe something related to pthreads has changed b/w the OSs??
So, my query is that is there any way that will assure that some processing in my app is timerised(and which is independent of the OS) without using QTimer as i think that QTimer is not a good option to achieve what i want??
What option can be there?? pthreads or Boost threads? which one would be better if i am to use threads as an alternate??But how can i make sure atleast a 3 second gap b/w successive updates no matter how long the update processing takes?
Kindly help.
Thanks.
If I was trying to get an acceptable, longer-term solution, I would investigate updating your display in a separate thread. In that thread, you could paint the display to an image, updating as often as you desire... although you might want to throttle the thread so it doesn't take all of the processing time available. Then in the UI thread, you could read that image and draw it to screen. That could improve your responsiveness to panning, since you could be displaying different parts of the image. You could update the image every 3 seconds based on a timer (just redraw from the source), or you could have the other thread emit a signal whenever the new data is completely refreshed.