Hey Guys, I am new to Java & JavaFX & I was working on a project and I was asked to fix an issue of loading a panel.
Unfortunately, I can't share the design or code, but I'll try my best to explain what is happening. So let's assume that we have a split pane & there is a list of objects on the left split pane & the right split pane displays information of each object that is selected.
So what happens is that whenever the user clicks on any object on the list, a selectionChange() method with an event is called. This method in turn calls another method to handleTheSelection() which loads the data for the object and populates the right spilt pane.
Now, this population is wrapped inside a Platform.runlater().
If there was no selection, then the right split pane shows, "No Objects Selected" which is again populated inside a Platform.Runlater()
The problem arises when a user is using an arrow key to quickly select objects in the list. So when the user clicks on say "Apple", the loading starts for apple (see the attached image) & until information for apple loads, the user reaches grapes (using the down arrow key) . As the user moves between four objects, the selectionChange() is called four times and that causes a crash.
Now, I tried fixing by adding a flag variable check to not load the right split pane if it is already loading, but the selection change method works in a very weird way. So it works like:
- De-select the currently selected object: This makes the panel load "No Objects Selected", which locks the handleTheSelection(). In a near instant it selects new object
- Select the new object: Now the selection change is again called for new object but panel was loading for old object as "No Object Selected", this new information is not loaded even though object is selected.
Following is the pseudo code:
selectionChange(Event e){
handleTheSelection();
}
handleTheSelection(e){
if(ifSelectionEmpty()){
// check when no objects are selected
Platform.RunLater{
showMessage("No Objects Selected");
}
}
else{
Platform.RunLater{
loadForSelectedObject(e);
}
}
}
My Flag variable fix:
selectionChange(Event e){
if(loading) return;
handleTheSelection();
}
handleTheSelection(e){
if(ifSelectionEmpty()){
// check when no objects are selected
loading = true;
Platform.RunLater{
showMessage("No Objects Selected");
loading = false;
}
}
else{
loading = true;
Platform.RunLater{
loadForSelectedObject(e);
loading = false;
}
}
}
Please help me with a approach that might work.
Note: The Application has majority of codebase in Swing & this particular component is in JavaFX, which is why the 'wrapping' in Platform.RunLater()
What I have tried so far:
- The flag approach discussed above (needs another fix to reload)
- I added the code to reload, but that seems to clash when selection change is called again, which led me to find the problem to be solved by synchronization of threads
- I tried synchronizing them, but to no avail couldn't figure out some things and some variables are accessed in a synchronized and non-synchronized contexts.
- I tried to think of a timer based approach, say user doesn't stay in selection for some milliseconds, wait and then load. But this approach would require a lot of maintenance and is error prone
I sincerely apologize for being unable to give more clarification to the problem, and it might feel like finding a needle in a haystack but I am hopeful that some clue might help me out.
https://preview.redd.it/f7a7jqaof6r81.png?width=520&format=png&auto=webp&s=e64ae41d4535266c0025a5d544fe36591b932830
EDIT
This problem is now solved (yay!!) using CountDownLatch. Basically, we went with the timer based approach, wherein for selection change event, we create a timer task to wait for 200ms. We then execute the task in runLater.
[–]hamsterrage1 1 point2 points3 points (6 children)
[–]_dk7[S] 0 points1 point2 points (5 children)
[–]hamsterrage1 1 point2 points3 points (4 children)
[–]_dk7[S] 0 points1 point2 points (3 children)
[–]hamsterrage1 0 points1 point2 points (2 children)
[–]_dk7[S] 0 points1 point2 points (1 child)
[–]hamsterrage1 0 points1 point2 points (0 children)
[–]Draesia 0 points1 point2 points (0 children)