JavaFX ListCell updateItem执行两次?

JavaFX ListCell updateItem执行两次?,java,listview,javafx,Java,Listview,Javafx,我试图在ListView中创建自定义单元格,但每次添加新项时,updateItem(TextFlow项,布尔空)都会执行两次:一次接收null和true,第二次不接收(!null和false) 如果我不执行setCellFactory方法,那么我可以将项目添加到表中而不会出现问题 但是,当我实现它时,它只会创建10个空单元格(内容在哪里?) 公共类控制器实现可初始化{ @FXML 私有ListView控制台; 私有ObservableList data=FXCollections.obser

我试图在ListView中创建自定义单元格,但每次添加新项时,updateItem(TextFlow项,布尔空)都会执行两次:一次接收nulltrue,第二次不接收(!nullfalse

如果我不执行setCellFactory方法,那么我可以将项目添加到表中而不会出现问题

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

公共类控制器实现可初始化{
@FXML
私有ListView控制台;
私有ObservableList data=FXCollections.observableArrayList();
公共void初始化(URL位置、ResourceBundle资源){
console.setCellFactory(新回调(){
@凌驾
公共ListCell调用(ListView参数){
返回新的ListCell(){
@凌驾
受保护的void updateItem(TextFlow项,布尔值为空){
super.updateItem(项,空);
如果(项!=null){
设置项目(项目);
setStyle(“-fx控件内部背景:蓝色;”);
}否则{
System.out.println(“项为空”);
}
}
};
}
});
对于(int i=0;i<10;i++){
Text txt=getStyledText(“这是项目编号“+i+”);
TextFlow TextFlow=新的TextFlow();
textFlow.getChildren().add(txt);
data.add(textFlow);
}
控制台。设置项(数据);
}
私有文本getStyledText(字符串输入文本){
文本文本=新文本(输入文本);
text.setFont(新字体(“Courier new”,12));
text.setFill(Paint.valueOf(“#000000”);
返回文本;
}
}

updateItem
可以调用任意次数,可以传递不同的项,单元格可以从空变为非空,反之亦然<代码>列表视图创建屏幕上显示的单元格数量,并用项目填充单元格。例如,滚动或修改
项目
列表或调整
列表视图
的大小可能会导致更新

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

此外,您应该避免自己调用
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.");
            }

        }
    };
}
@覆盖
公共ListCell调用(ListView参数){
返回新的ListCell(){
@凌驾
受保护的void updateItem(TextFlow项,布尔值为空){
super.updateItem(项,空);
如果(项!=null){
setStyle(“-fx控件内部背景:蓝色;”);
设置图形(项目);
}否则{
设置样式(空);
设置图形(空);
System.out.println(“项为空”);
}
}
};
}

updateItem
可以调用任意次数,可以传递不同的项,单元格可以从空变为非空,反之亦然<代码>列表视图创建屏幕上显示的单元格数量,并用项目填充单元格。例如,滚动或修改
项目
列表或调整
列表视图
的大小可能会导致更新

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

此外,您应该避免自己调用
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.");
            }

        }
    };
}
@覆盖
公共ListCell调用(ListView参数){
返回新的ListCell(){
@凌驾
受保护的void updateItem(TextFlow项,布尔值为空){
super.updateItem(项,空);
如果(项!=null){
setStyle(“-fx控件内部背景:蓝色;”);
设置图形(项目);
}否则{
设置样式(空);
设置图形(空);
System.out.println(“项为空”);
}
}
};
}

我认为传递
节点是个坏主意?@Sedrick是的,但我在回答中只关注了一个问题。@fabian为什么传递
节点是个坏主意?@Raccoon a)你只能在场景中添加一次节点。例如,如果要在
列表视图旁边显示所选节点,则会出现问题。而且,通过这种方式很难获得关于给定项目的数据的任何信息。b) 
Node
s通常是大对象,虚拟化视图的全部目的是将使用的节点数减少到一个较小的数目(可见节点)。如果将创建
节点所用的数据添加到项目列表中,并对不同项目的单元格重复使用用作geaphic的节点,您应该希望这样做,而不是同时将所有节点保留在内存中。@fabian这是有道理的!谢谢。我认为传递
节点是个坏主意?@Sedrick是的,但我在回答中只关注了一个问题。@fabian为什么传递
节点是个坏主意?@Raccoon a)你只能在场景中添加一次节点。例如,如果要在
列表视图旁边显示所选节点,则会出现问题。而且,通过这种方式很难获得关于给定项目的数据的任何信息。b) 
Node
s通常是大对象,虚拟化视图的全部目的是将使用的节点数减少到一个较小的数目(可见节点)。如果添加数据,您将从中创建
节点
s,然后重新使用