Run a task every loop of the JavaFX Platform Thread? - javafx

I have a JavaFX UI that displays a relatively large data set. When the data set is changed, the changes are queued up and then the changes need to be "pushed" to the UI. Often there are more changes in the queue than I can push to the UI in one Platform.runLater() -- trying to push them all causes the JavaFX window to stutter or freeze.
Since the changes are in a queue, it's easy for me to break them into a series of batches. I would like to run a batch each time the javaFX ui thread loops.
How do I connect to the FX thread so it calls my method once every loop? In addition, about how many milliseconds can I responsibly use per-loop to update the data set?

Related

Can I delay/bundle reactions to QPlainTextEditor.textChanged events?

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.

Is using Timeline for scheduling correct

I've found a lot of suggestions to use Timeline with KeyFrame.onFinished to schedule tasks in the JavaFX. But the AnimationTimer doc says, that its handle method is called 60 times per second.
It is unclear from documentation but it seems that Timeline uses AnimationTimer internally. Does that means that the timeline solution for scheduling imposes CPU-intensive polling mode? If that is actually how JavaFX works, what other methods for scheduling is recommended?
Advised Usage Rules for Scheduling in JavaFX
Given how Timeline works (see below), some basic rules can be derived:
Use a Timeline when you want to schedule quick operations that modify attributes of the scene graph.
Do not use a Timeline when you want to do any of the following:
Perform operations that are themselves time-consuming (e.g. the work for a given scheduled activity takes longer than 1/30th of a second).
Perform work which really doesn't have anything to do with the scene graph.
Have real-time scheduling at a resolution greater than a pulse (1/60th of a second).
Control your scheduling using traditional java.util.concurrent mechanisms or a third party library.
Run your scheduled tasks on their own threads.
Also, for a one-off execution that updates the scene graph after a fixed delay, I like to use a PauseTransition.
Answers to specific questions and concerns
It is unclear from documentation but it seems that Timeline uses AnimationTimer internally.
No, Timeline does not use AnimationTimer internally. However, Timeline is still pulse based and will receive code to update the current state of the timeline will be invoked on each pulse (usually 60 times a second). To understand what a pulse is read the background section below.
Does that means that the timeline solution for scheduling imposes CPU-intensive polling mode?
Yes, there is some overhead, but it is likely minimal enough that it can be disregarded. The JavaFX system is going to be running some work on each pulse anyway, regardless whether you create any timelines yourself. Unless you are heavily animating objects or doing a lot of work on each pulse, then the time to process each pulse will be completely trivial as there is simply very little work to be done on each pulse.
If that is actually how JavaFX works, what other methods for scheduling is recommended?
There are numerous alternatives to Timeline:
Use a javafx.concurrent facility such as a Task or Service, and specifically a ScheduledService.
This is good if you want to provide feedback (such as progress, message updates and return values) to the JavaFX UI.
Use a java.util.concurrent facility.
This is good if you don't need the additional features of javafx.concurrent for progress and messaging or if you want the additional control provided by java.util.concurrent facilities.
If you use this, you can still get intermittent or final feedback to your JavaFX UI by invoking Platform.runLater().
Use a java.util.TimerTask.
Simpler API than java.util.concurrent, no direct interface for JavaFX feedback, though again you can use Platform.runLater() for that.
Use a third party scheduling system (such as Quartz):
More complicated than other solutions, but also more flexible, though it adds a dependent library and requires Platform.runLater if you want to modify scene graph elements.
If you do use something other than a timeline, you need to take care:
You invoke Platform.runLater if you want to modify anything on the scene graph from your non-JavaFX application threads.
You don't invoke Platform.runLater too often so as to overload the JavaFX application thread (e.g. by coalescing update calls).
Background Info
Timeline Operation
For example, let's say you have a Timeline which has a Keyframe that has a duration of 1 second. The internal Timeline will still be updated each pulse. This is required because a Timeline is more than just a scheduler, it has other properties and tasks. For instance the Timeline has a currentTime property. The currentTime will be updated each pulse, so that it always reflects the current time accurately. Similarly, internal logic with the Timeline will check to see if there are any KeyValues associated with the Timeline, and update their values on each pulse, in accordance with their associated Interpolator. And the internal logic will check on each pulse to see if the Timeline is finished, to call the onFinished handler. It will also evaluate the current time versus the duration of each keyframe and, if there is a match, fire the appropriate action event for the keyframe.
So the Timeline is acting like a scheduler in that it can execute key frames at specific times, but it is more than a scheduler as it also maintains it's current time, current state and ability to continuously vary associated key values. Additionally, you can vary the rate, direction and number of cycles of a timeline, as well as pause it in position, then resume it, which also differs from a traditional scheduler.
An aspect of the Timeline is that because it is based upon callbacks from pulses in the JavaFX system; everything runs on the JavaFX application thread. Therefore, when you use timelines (even 1000 of them), no additional threads are spawned, so from that perspective it is lightweight. Also all logic invoked by the timeline occurs on the JavaFX application thread. Because everything runs on the JavaFX application thread, this makes the Timeline nice for manipulating elements and attributes of the active JavaFX scene graph (such manipulations must be performed on the JavaFX application thread). However, a timeline would be a bad choice if you wanted to do a lot of CPU time-consuming work or blocking I/O in the associated timeline keyframes. This is because the JavaFX application thread will be blocked while that work occurs, freezing your UI.
Pulses
The JavaFX runtime system is based upon pulses.
A pulse is an event that indicates to the JavaFX scene graph that it is time to synchronize the state of the elements on the scene graph with Prism. A pulse is throttled at 60 frames per second (fps) maximum and is fired whenever animations are running on the scene graph. Even when animation is not running, a pulse is scheduled when something in the scene graph is changed. For example, if a position of a button is changed, a pulse is scheduled.
When a pulse is fired, the state of the elements on the scene graph is synchronized down to the rendering layer. A pulse enables application developers a way to handle events asynchronously. This important feature allows the system to batch and execute events on the pulse.
The JavaFX animation system stores a list of all of the animations and animation timers which been created and not garbage collected. On each pulse it will iterate through this list. Each animation timer will have it's handle callback invoked on each pulse. Each timeline or transition will similarly have its internal state update and update any associated key values or fire key frame action events as appropriate.
You can use ScheduledExecutorService
final Runnable runnable = new Runnable() {
public void run() {
//Code goes here
}
}
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleAtFixedRate(runnable, 0, 1, TimeUnit.SECONDS);

Qt to update (repaint) textbox while processing

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.

How to update a GUI component in Qt?

I am loading a set of 100 images to a QTableWidget. Since it takes about 4 seconds loading, I want to show a progress bar (customised one) with activity indicators or spinner etc. How could I update the GUI and the progress bar simultaneously, by signals & slots, and after loading the images?
Your event loop is busy with your main task, so it can't process your request. All slots will be called after event loop is free. Your options are:
Move slow processing to another thread. That may be not an option here because you can't interact with Qt's widgets in non-main thread.
Call QApplication::processEvents() each time when you want your GUI changes to apply. This is a common and simple solution. This function will execute your slots (if any calls are sheduled), updates GUI and returns execution flow to you.
A better way to load your images would be using a QThread that emits a signal as it processes the images, and connect that signal to a slot in your main widget, here you'll find a couple of examples

QTimer firing issue in QGIS(Quantum GIS)

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.

Resources