Reputation: 1670
I have a JavaFX with TabPane which holds Java Objects with data into different tabs. I found that when the content of the tab takes time to load because there are SQL queries for execution the application just hangs. Is there any way to display some "Loading" message during the content utilization? for example:
Tab.setContent(<some_heavy_Java_Object>);
Is there any workaround to solve this in JavaFX or Java?
P.S I tested this code sample but I get error when I try to run the code:
TabContentInfrastructure content;
class GetDailySalesService extends Service<ObservableList<Object>>
{
@Override
protected Task createTask()
{
return new GetDailySalesTask();
}
}
class GetDailySalesTask extends Task<ObservableList<Object>>
{
@Override
protected ObservableList<Object> call() throws Exception
{
content = new TabContentInfrastructure();
return (ObservableList<Object>) content.initTestTabContentData();
}
}
..........
VBox vbox = new VBox();
content = new TabContentInfrastructure();
vbox.getChildren().add(content.initTestTabContentData());
GetDailySalesService service = new GetDailySalesService();
Region veil = new Region();
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
veil.setPrefSize(240, 160);
ProgressIndicator p = new ProgressIndicator();
p.setMaxSize(140, 140);
p.progressProperty().bind(service.progressProperty());
veil.visibleProperty().bind(service.runningProperty());
p.visibleProperty().bind(service.runningProperty());
//tableView.itemsProperty().bind(service.valueProperty());
StackPane stack = new StackPane();
stack.getChildren().addAll(vbox, veil, p);
service.start();
tabdata.setContent(stack);
Can you help me to solve this issue.
Another attempt to solve the issue:
Task<VBox> task = new Task<VBox>()
{
@Override
protected VBox call() throws Exception
{
TabContentInfrastructure content = new TabContentInfrastructure();
return content.initTestTabContentData();
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
Region veil = new Region();
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
veil.setPrefSize(240, 160);
ProgressIndicator p = new ProgressIndicator();
p.setMaxSize(140, 140);
//p.progressProperty().bind(service.progressProperty());
veil.visibleProperty().bind(task.runningProperty());
p.visibleProperty().bind(task.runningProperty());
//vb.visibleProperty().bind(service.runningProperty().not());
//tableView.itemsProperty().bind(service.valueProperty());
StackPane stack = new StackPane();
task.setOnSucceeded(new EventHandler<WorkerStateEvent>()
{
@Override
public void handle(WorkerStateEvent t){
System.out.print("Entered setOnSucceeded**********" + t.getSource().getValue());
stack.getChildren().clear();
stack.getChildren().addAll(task.getValue());
}
});
stack.getChildren().addAll(veil, p);
tabdata.setContent(stack);
This time the result is null.
And another unsuccessful attempt.
StackPane stack = new StackPane();
Region veil = new Region();
ProgressIndicator p = new ProgressIndicator();
Task<VBox> task = new Task<VBox>()
{ // create new task
@Override
public VBox call() throws InterruptedException
{
Platform.runLater(new Runnable()
{ // USE THIS INSTEAD
@Override
public void run()
{
try
{
// ui updates here(inside application thread)
// this is needed if you want to update your ui
// you cannot update any ui from outside the application thread
TabContentInfrastructure content = new TabContentInfrastructure();
//stack.getChildren().clear();
stack.getChildren().addAll(content.initTestTabContentData());
}
catch (InterruptedException ex)
{
//Logger.getLogger(InfrastructureDataTabs.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
return null;
}
};
new Thread(task).start();
veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
veil.setPrefSize(240, 160);
p.setMaxSize(140, 140);
p.progressProperty().bind(task.progressProperty());
veil.visibleProperty().bind(task.runningProperty());
p.visibleProperty().bind(task.runningProperty());
//vb.visibleProperty().bind(service.runningProperty().not());
//tableView.itemsProperty().bind(service.valueProperty());
stack.getChildren().addAll(veil, p);
tabdata.setContent(stack);
Upvotes: 0
Views: 1953
Reputation: 36742
you must load the data in a different Task Thread, I see that you are trying to do the same. The problem with your code is that you are not updating your progress bar. You must use updateProgress as shown here
http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm#BABGJIDB
Here is a very nice example from Jewelsea where he has very nicely displayed the use of Task and how to use it to update the progress on the UI
Update progress bar and multiple labels from thread
Here you can find out how to use the Task as well as update the UI from the task
Some more Nice examples are
https://community.oracle.com/message/9927179#9927179
https://community.oracle.com/message/10631701#10631701
Upvotes: 3
Reputation: 1022
You should just execute the expensive computations in another thread and then update e.g. a progresss bar in the javafx application thread.
Also your application wont hang during the process anymore.
Like this:
Task task = new Task<Void>() { // create new task
@Override
public Void call() {
// do expensive computations here
Platform.runLater(new Runnable() { // return to application thread
@Override
public void run() {
// ui updates here(inside application thread)
}
});
return null;
}
};
new Thread(task).start(); // execute task in new thread
Hope it helps, Laurenz.
EDIT -------------
Task<Void> task = new Task<Void>() { // create new task
@Override
public Void call() {
try {
Thread.sleep(50); // this simulates expensive computations(in your case loading) - your app would hang for this duration
} catch (InterruptedException e) {
e.printStackTrace();
}
// REMOVE THE SLEEP AND PUT YOUR TASK HERE
// Main.this.root.setPrefHeight(50); // would NOT work(because outside application thread)
Platform.runLater(new Runnable() { // USE THIS INSTEAD
@Override
public void run() {
// ui updates here(inside application thread)
// this is needed if you want to update your ui
// you cannot update any ui from outside the application thread
}
});
return null;
}
};
new Thread(task).start(); // execute task in new thread
Upvotes: 3