启动任务时没有响应的ui

0kjbasz6  于 2021-06-30  发布在  Java
关注(0)|答案(2)|浏览(344)

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

np8igboo

np8igboo1#

下面是我如何做到的。基本上,我启动一个新任务,并让一个侦听器成功完成该任务。costingservice是一个到MSSQLServerDB的接口hibernate连接(通过glassfish)。该接口上的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;
}
sqyvllje

sqyvllje2#

您可以将listview定义为字符串的listview,将任务定义为字符串的observablelist的任务。之后,只需将listview的items属性绑定到task 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();
}

希望有帮助。

相关问题