滚动后TableView组合框显示问题

时间:2016-11-01 00:14:47

标签: java javafx

我在滚动后面临显示问题。我的movieSubtitleTableColumn单元格中的一些组合框应该是空的,它们正在填充其他组合框中的相同项和值。此外,在滚动之前正确填充的组合框即使在滚动之后也保留了正确的项目和值。 所以,出于某种原因,问题只发生在空洞的问题上。

控制器:

@FXML
private TableView<Movie> moviesTableView;
@FXML
private TableColumn<Movie, String> movieTitleTableColumn;
@FXML
private TableColumn<Movie, Subtitle> movieSubtitleTableColumn;

private ObservableList<Movie> movieList;

private void setupTableView(List<Movie> movieList) {
    this.movieList = FXCollections.observableList(movieList);
    moviesTableView.getItems().addAll(this.movieList);
    movieTitleTableColumn.setCellValueFactory(c -> new SimpleStringProperty(c.getValue().getMovieFile().getName()));
}

private void populateSubtitleChoiceBox() {
    if (!movieList.isEmpty()) {
        movieSubtitleTableColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue().getMovieSubtitle()));
        movieSubtitleTableColumn.setCellFactory(col -> {
            ComboBox<SubtitleInfo> combo = new ComboBox<>();
            combo.setMaxWidth(Double.MAX_VALUE);
            combo.setConverter(
                    new StringConverter<SubtitleInfo>() {
                        @Override
                        public String toString(SubtitleInfo subtitleInfo) {
                            if (subtitleInfo == null) {
                                return null;
                            } else {
                                return subtitleInfo.getFileName();
                            }
                        }
                        @Override
                        public SubtitleInfo fromString(String s) {
                            return null;
                        }
                    });

            TableCell<Movie, Subtitle> cell = new TableCell<Movie, Subtitle>() {
                @Override
                protected void updateItem(Subtitle subInfo, boolean empty) {
                    super.updateItem(subInfo, empty);
                    if (empty) {
                        setGraphic(null);
                    } else {
                        if (subInfo != null) {
                            combo.getItems().setAll(subInfo.getSubtitleList());
                            combo.setValue(subInfo.getSubtitleSelected());
                        }
                        setGraphic(combo);
                    }
                }
            };

            combo.valueProperty().addListener((obs, oldValue, newValue) ->
                    cell.getItem().setSubtitleSelected(newValue));

            return cell;
        });
    }
}

型号:

public class Movie {
    private File movieFile;
    private Subtitle movieSubtitle;
    private BooleanProperty movieSubDownload = new SimpleBooleanProperty(false);
    //getters setters
}

public class Subtitle {
    private List<SubtitleInfo> subtitleList = new ArrayList<>();
    private SubtitleInfo subtitleSelected;
    //getters setters
}

在调用populateSubtitleChoiceBox()之前,我更新了我的movieList:

for (Movie movie : movieList) {
   //do stuff
   movie.setMovieSubtitle(subtitle);
}
populateSubtitleChoiceBox();

屏幕截图:

Before scrolling (Correct Display)

After scrolling (Comboboxes that were supposed to be empty they are not anymore)

编辑: 目前我通过将图形设置为null来掩盖问题:

        TableCell<Movie, Subtitle> cell = new TableCell<Movie, Subtitle>() {
            @Override
            protected void updateItem(Subtitle subInfo, boolean empty) {
                super.updateItem(subInfo, empty);
                if (empty || subInfo == null || subInfo.getSubtitleList().isEmpty()) {
                    setGraphic(null);
                } else {
                    combo.getItems().setAll(subInfo.getSubtitleList());
                    combo.setValue(subInfo.getSubtitleSelected());
                    setGraphic(combo);
                }
            }
        };

虽然我仍然不知道如何正确修复它,为什么会发生这种情况。如果您需要我的代码的任何其他部分,请告诉我。感谢

1 个答案:

答案 0 :(得分:0)

当您的单元格被重复使用时(例如在滚动期间),对updateItem(...)方法的调用将重复调用

combo.getItems().addAll(...);

在同一个组合框中,因此您只需在组合框的项目列表中添加越来越多的元素。您应该每次都替换所有项目,因此只需调用setAll(...)

来替换该方法调用
combo.getItems().setAll(subInfo.getSubtitleInfoObservableList());