首页 > 解决方案 > 在没有阻塞 UI 线程的情况下更新 tableview javafx

问题描述

每次更新用户界面时,我都会不断地从我的数据库(每 2 秒)中提取数据(大约 10-15 个项目)。

我尝试使用预定服务、线程和任务来更新 UI,但它总是冻结。

我也尝试过使用可观察列表作为 tableview 并且只是 removeAll() 和 addAll() (根据JavaFX 2.1 TableView refresh items

有没有办法避免阻塞ui线程?

编辑:

如果我删除 tableViewConcern.getItems().setAll(service.getValue()); 它不会滞后 部分,但是一旦我开始向数据库中添加东西,它就会变得越来越慢(直到它停止)。

在我的ActiveConcernService (ScheduledService) 中,它只是从数据库中获取数据。

public class ActiveConcernService extends ScheduledService<ObservableList<Concern>> {
    private UserAccount currentUser;
    public ActiveConcernService(UserAccount currentUser) {
        this.currentUser = currentUser;
    }

public final ObservableList<Concern> getConcerns() {
    ObservableList<Concern> concerns;
    if(RoleService.getInstance().getById(currentUser.getRoleId()).getTitle().equals(Role.DefaultRole.ADMIN.getRole())){
        concerns = FXCollections.observableList(ConcernService.getInstance().allNotDone());         
    } else {
        concerns = FXCollections.observableList(ConcernService.getInstance().allByUser(currentUser));           
    }
    return concerns; //gets the data from database base on the user role
}

@Override
protected Task<ObservableList<Concern>> createTask() {
    return new Task<ObservableList<Concern>>() {
        @Override
        protected ObservableList<Concern> call() {
            return getConcerns();
        }
    };
}

在我的控制器中,这就是我初始化表列标题的方式,而 scheduleservice 确实是使用表的唯一两个部分。

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    // Initializes other ui elements (textfield, button, choicebox, etc)
    initializeConcernTable();
    ActiveConcernService service = new ActiveConcernService(currentUser);
    service.setPeriod(Duration.millis(2000));
    service.setOnSucceeded((t) -> {
        tableViewConcern.getItems().setAll(service.getValue()); //Everytime this executes it lags
    });
    service.start();
}

private void initializeConcernTable() {

    TableColumn<Concern, String> clientColumn = new TableColumn<>(Concern.NAME_HEADER);
    clientColumn.setCellValueFactory(param -> param.getValue().getClientNameProperty());
    clientColumn.setMinWidth(125);
    clientColumn.setSortable(false);

    TableColumn<Concern, String> remarkColumn = new TableColumn<>(Concern.REMARK_HEADER);
    remarkColumn.setCellValueFactory(param -> param.getValue().getRemarkProperty());
    remarkColumn.setMinWidth(175);
    remarkColumn.setSortable(false);

    TableColumn<Concern, String> categoryColumn = new TableColumn<>(Concern.CATEGORY_HEADER);
    categoryColumn.setCellValueFactory(param -> new SimpleStringProperty(
            CategoryService.getInstance().getById(param.getValue().getCatergoryId()).getTitle()));
    categoryColumn.setMinWidth(150);
    categoryColumn.setSortable(false);

    TableColumn<Concern, String> assignToColumn = new TableColumn<>(Concern.EMPLOYEE_HEADER);
    assignToColumn.setCellValueFactory(param -> new SimpleStringProperty(
            UserAccountService.getInstance().getById(param.getValue().getUserAccountId()).getName()));
    assignToColumn.setMinWidth(125);
    assignToColumn.setSortable(false);

    TableColumn<Concern, String> numberColumn = new TableColumn<>(Concern.NUMBER_HEADER);
    numberColumn.setCellValueFactory(param -> new ReadOnlyObjectWrapper<String>(param.getValue().getNumber() + ""));
    numberColumn.setSortable(false);

    TableColumn<Concern, String> dateColumn = new TableColumn<>(Concern.DATE_HEADER);
    dateColumn.setCellValueFactory(param -> new SimpleStringProperty(
            param.getValue().getIssuedOn().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))));
    dateColumn.setPrefWidth(150);
    dateColumn.setSortable(false);

    tableViewConcern.getColumns().addAll(numberColumn, assignToColumn, clientColumn, categoryColumn, remarkColumn,
            dateColumn);
}

标签: javajavafx

解决方案


问题是每次表更新时都会调用数据库。

    TableColumn<Concern, String> categoryColumn = new TableColumn<>(Concern.CATEGORY_HEADER);
    categoryColumn.setCellValueFactory(param -> new SimpleStringProperty(
            CategoryService.getInstance().getById(param.getValue().getCatergoryId()).getTitle())); //This part was the one that was making it lag
    categoryColumn.setMinWidth(150);
    categoryColumn.setSortable(false);

    TableColumn<Concern, String> assignToColumn = new TableColumn<>(Concern.EMPLOYEE_HEADER);
    assignToColumn.setCellValueFactory(param -> new SimpleStringProperty(
            UserAccountService.getInstance().getById(param.getValue().getUserAccountId()).getName())) ; //This part was the one that was making it lag
    assignToColumn.setMinWidth(125);
    assignToColumn.setSortable(false);

我通过制作本地副本而不是每次都调用数据库来解决它

谢谢费边


推荐阅读