我有一个Task应该从数据库中返回SomeObject
列表:
public final class LoadTask extends Task<List<SomeObject>> {
@Override
protected List<TodoTask> call() throws InterruptedException {
List<SomeObject> list = FXCollections.observableArrayList();
list.addAll(servcie.getAllSomeObjects());
// this task take a lot of time
return list;
}
}
我使用此任务填充TableView
:
@FXML
private void pullData() throws InterruptedException, ExecutionException {
loadTask1 = new LoadTask();
final Thread t = new Thread(loadTask1);
t.start();
todoList.getItems().addAll(loadTask1.get());
}
当我按下执行pullData()
整个UI
冻结的按钮,直到我从数据库中获取所有对象。
如何修复设计以获得响应式UI
?
答案 0 :(得分:0)
以下是我如何实现它。基本上,我开始一项新任务,并将监听器放在该任务上以便成功完成。 costingService是一个接口hibernate连接(通过glassfish)到MS SqlServer DB。该接口上的listProducts方法返回数据库中的所有产品。 loadTask包含任务完成时数据库查询的结果。 pricingProductTableList是查询结果的ObservableList,而pricingProductTable是显示数据的TableView。这是代码:
private ObservableList<Product> getProductList() {
logger.info("Entering {}.getProductList", this.getClass().getName());
if (costingService == null) {
return null;
}
final Task<ObservableList> loadTask = new Task<ObservableList>() {
@Override
protected ObservableList call() throws Exception {
return FXCollections.observableList(costingService.listProducts());
}
};
loadTask.stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends Worker.State> source, Worker.State oldState, Worker.State newState) {
if (newState.equals(Worker.State.SUCCEEDED)) {
if (pricingProductTableList != null && !pricingProductTableList.isEmpty()) { // moved here from beginning of method, now table doesn't redraw
pricingProductTableList.clear();
}
pricingProductTableList = loadTask.getValue();
pricingProductTable.getItems().setAll(pricingProductTableList);
pricingProductTable.getColumns().get(0).setVisible(false);
pricingProductTable.getColumns().get(0).setVisible(true);
}
} else if (newState.equals(Worker.State.FAILED)) {
loadTask.getException().printStackTrace();
}
}
});
new Thread(loadTask).start();
return pricingProductTableList;
}
答案 1 :(得分:0)
您可以将ListView定义为String的ListView,将您的任务定义为String的ObservableList的任务。之后,您可以将listview的items属性绑定到任务值属性,如下所示:
listview.itemsProperty().bind(task.valueProperty());
这是一个更大的例子:
public void start(Stage stage) throws Exception {
VBox vbox = new VBox(10.0);
vbox.setAlignment(Pos.CENTER);
final ListView<String> listview = new ListView<String>();
final ProgressBar bar = new ProgressBar(-1);
bar.setVisible(false);
final Button button = new Button("Fill");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
final Task<ObservableList<String>> task = new Task<ObservableList<String>>() {
@Override
protected ObservableList<String> call() throws Exception {
ObservableList<String> items = FXCollections.observableArrayList();
for (int i = 0; i < 50000; i++) {
items.add("Row#"+i);
}
return items;
}
};
bar.visibleProperty().bind(task.runningProperty());
button.disableProperty().bind(task.runningProperty());
listview.itemsProperty().bind(task.valueProperty());
Thread t = new Thread(task);
t.start();
}
});
vbox.getChildren().addAll(listview, button, bar);
Scene scene = new Scene(vbox, 300, 300);
stage.setScene(scene);
stage.show();
}
希望它有所帮助。