删除自定义ListCell时,JavaFX ListView无法正确刷新

时间:2017-10-24 18:27:52

标签: listview javafx

我正在为我的测验申请编辑。

我有一个自定义ListCell<Question>类,如下所示:

public class QuestionListCell extends ListCell<Question> {

private static final Logger LOGGER = Logger.getLogger(QuizLoader.class.getName());

@FXML HBox cellBox;
@FXML Label title;
@FXML GridPane answersGrid;

private FXMLLoader loader;

@Override
protected void updateItem(Question item, boolean empty) {
    super.updateItem(item, empty);
    if (empty || item == null) {
        setText(null);
        setGraphic(null);
    }
    else {
        if (loader == null) {
            loader = new FXMLLoader(getClass().getResource(QUESTION_LIST_CELL_FXML));
            loader.setController(this);
            try {
                loader.load();
            }
            catch (IOException e) {
                LOGGER.log(Level.SEVERE, e.getMessage(), e);
            }
        }
        addContent(item);
    }
}

private void addContent(Question question) {
    title.textProperty().bind(question.getQuestionTextProperty());

    int answersSize = question.getAnswers().size();
    for (int i = 0; i < answersSize; i++) {
        int rowIndex = i / 2;
        int colIndex = i % 2 == 0 ? 0 : 1;

        Label answerLabel = new Label();
        answerLabel.textProperty().bind(question.getAnswers().get(i).getAnswerTextProperty());
        answerLabel.prefWidthProperty().bind(Bindings.divide(answersGrid.widthProperty(), 2));
        answersGrid.add(answerLabel, colIndex, rowIndex);
    }

    final NumberBinding cellBoxWidth = Bindings.subtract(getListView().widthProperty(), 20);
    cellBox.prefWidthProperty().bind(cellBoxWidth);
    answersGrid.prefWidthProperty().bind(cellBoxWidth);
    setGraphic(cellBox);
}

}

我在MainController中设置了ListView,如下所示:

@FXML
private void onAddButtonClicked() {
    LOGGER.log(Level.INFO, "addButton clicked.");
    // quiz.getQuestions().add(quiz.getQuestions().get(0));
}

@FXML
private void onDeleteButtonClicked() {
    LOGGER.log(Level.INFO, "deleteButton clicked.");

    int index = listView.getSelectionModel().getSelectedIndex();
    if (index >= 0) {
        quiz.getQuestions().remove(index);
    }
}

private void setUpQuestionsListView() {
    listView.setCellFactory(listView -> new QuestionListCell());
    listView.itemsProperty().bindBidirectional(quiz.getQuestionsProperty());
}

到目前为止,ListView看起来像这样:

enter image description here

但是,当我删除第一个(也是第一个)项目时,第二个项目的GridPane似乎覆盖在第一个项目上。

enter image description here

如果我在ListView中有更多元素,那么这不会发生,据我所知,只有剩下两个元素并且我删除了第一个元素。我做错了什么?

1 个答案:

答案 0 :(得分:1)

添加行

answersGrid.getChildren().clear() ;

addContent()的开头(或者,如果您愿意,可以在updateItem()中,在致电addContent()之前)。

问题是你只为每个细胞加载一次FXML(这是一件好事);如果(何时)该单元格随后被重用,则在不更改updateItem()引用的情况下再次调用answersGrid,并且您可以向网格中添加更多子项而不删除原始子项。因此,当重复使用单元格时(例如通过滚动,或者当项目被删除并且其单元格被重用于另一个项目时),多个节点被添加到网格中的相同位置。

如上所述,从网格中删除现有标签将解决问题。