0

我有一个任务应该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

4

2 回答 2

0

您可以将 ListView 定义为 String 的 ListView,将 Task 定义为 String 的 ObservableList 的 Task。之后,您只需将 listview 的 items 属性绑定到任务 value 属性,如下所示:

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();
}

希望能帮助到你。

于 2013-06-07T07:48:12.173 回答
0

这是我如何完成它。基本上,我开始一项新任务,并在该任务上放置一个侦听器以成功完成。costingService 是一个到 MS SqlServer DB 的接口休眠连接(通过 glassfish)。该接口上的 listProducts 方法返回数据库中的所有产品。loadTask 包含任务完成时数据库查询的结果。定价产品表列表是查询结果的ObservableList,定价产品表是显示数据的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;
}
于 2013-06-06T15:12:27.927 回答