JavaFX ListCell updateItem执行两次?

时间:2019-07-13 13:02:35

标签: java listview javafx

我试图在ListView中创建自定义单元格,但是每次添加新项时,都会执行两次 updateItem(TextFlow项目,布尔空):一次它收到 null true ,第二次不这样做(!null false

如果我实现 setCellFactory 方法,那么我可以毫无问题地将项目添加到表中。

ListView without custom cellFactory

但是,当我实现它时,它只是创建了10个空单元(内容在哪里?)。

ListView with custom cellFactory

public class Controller implements Initializable {

@FXML
private ListView <TextFlow> console;

private ObservableList<TextFlow> data = FXCollections.observableArrayList();

public void initialize(URL location, ResourceBundle resources) {

    console.setCellFactory(new Callback<ListView<TextFlow>, ListCell<TextFlow>>() {

        @Override
        public ListCell<TextFlow> call(ListView<TextFlow> param) {
            return new ListCell<TextFlow>() {
                @Override
                protected void updateItem(TextFlow item, boolean empty) {
                    super.updateItem(item, empty);

                    if (item != null) {
                        setItem(item);
                        setStyle("-fx-control-inner-background: blue;");
                    } else {
                        System.out.println("Item is null.");
                    }

                }
            };
        }

    });


    for (int i = 0 ; i < 10; i++) {
        Text txt = getStyledText("This is item number " + i + ".");
        TextFlow textFlow = new TextFlow();
        textFlow.getChildren().add(txt);
        data.add(textFlow);
    }

    console.setItems(data);

}

private Text getStyledText (String inputText) {
    Text text = new Text(inputText);
    text.setFont(new Font("Courier New",12));
    text.setFill(Paint.valueOf("#000000"));
    return text;
}
}

1 个答案:

答案 0 :(得分:2)

updateItem可以被调用任意次,可以传递不同的项目,并且单元可以从空变为非空,反之亦然。 ListView会创建与您在屏幕上看到的单元格差不多的单元格,并在其中填充项目。例如。滚动或修改items列表或调整ListView的大小都会导致更新。

因此,任何单元都需要能够处理传递给null方法的任意顺序的项目(或updateItem +空)。

此外,您应该避免自己调用setItem,因为super.updateItem已经这样做了。如果要在单元格中显示项目,请改用setGraphic

@Override
public ListCell<TextFlow> call(ListView<TextFlow> param) {
    return new ListCell<TextFlow>() {
        @Override
        protected void updateItem(TextFlow item, boolean empty) {
            super.updateItem(item, empty);

            if (item != null) {
                setStyle("-fx-control-inner-background: blue;");
                setGraphic(item);
            } else {
                setStyle(null);
                setGraphic(null);
                System.out.println("Item is null.");
            }

        }
    };
}