我有一个带TabPane的JavaFX,它将带有数据的Java对象保存到不同的选项卡中。我发现当选项卡的内容需要时间加载时,因为有SQL查询要执行,应用程序才会挂起。在内容使用期间有没有办法显示一些“正在加载”的消息?例如:
Tab.setContent(<some_heavy_Java_Object>);
在JavaFX或Java中有解决方法吗?
P.S我测试了这段代码示例,但是当我尝试运行代码时出现错误:
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);
你能帮我解决这个问题。
解决问题的另一种尝试:
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);
这次结果为空。
又一次失败的尝试。
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);
答案 0 :(得分:3)
你应该只在另一个线程中执行昂贵的计算然后更新,例如javafx应用程序线程中的进度条 此外,您的应用程序将不再在此过程中挂起。
像这样:
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
希望它有所帮助,Laurenz。
编辑-------------
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
答案 1 :(得分:3)
你必须在不同的任务线程中加载数据,我看到你正在尝试做同样的事情。代码的问题在于您没有更新进度条。您必须使用updateProgress,如此处所示
http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm#BABGJIDB
以下是来自Jewelsea的一个非常好的示例,他非常好地展示了Task的使用以及如何使用它来更新UI上的进度
Update progress bar and multiple labels from thread
在这里,您可以了解如何使用任务以及从任务
更新UI更好的例子是