为什么super.updateItem(item,empty)在javafx中的listview.cellFacoty方法中调用?

时间:2014-03-22 04:31:46

标签: java javafx javafx-2 javafx-8

代码:

mpcListView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
    @Override
    public ListCell<String> call(ListView<String> param){
        return new XCell();
    }
});

public class XCell extends ListCell<String>{
    HBox hbox = new HBox();
    Label label = new Label();
    Button button = new Button("",getImage());
    String lastItem;

    public XCell(){
        super();
        hbox.setSpacing(120);
        hbox.getChildren().addAll(label,button);
        button.setOnAction(new EventHandler<ActionEvent>(){
            @Override
            public void handle(ActionEvent event){
                mpcListView.getItems().remove(lastItem);
            }
        });
    }

    @Override
    protected void updateItem(String item, boolean empty){
        super.updateItem(item, empty);
        if (empty){
            lastItem = null;
            setGraphic(null);
        }else{
            lastItem = item;
            label.setText(item);
            setGraphic(hbox);
        }
    }
}

为什么要调用super.updateItem(item, empty)

2 个答案:

答案 0 :(得分:3)

ListCell updateItem(...)实现非常重要,因为它调用Cell updateItem(...)实现来检查它是否为空并调用正确的方法:setItem(...)或setEmpty(.. )。

如果不调用super.updateItem(...),则不调用Cell.updateItem(...)并且不调用setItem(...)然后...没有绘制任何内容或者值是没有更新! ListCell在使用Cell updateItem实现之前只添加了一些检查,因此您有两个选择:

  • 您可以在自定义ListCell实现中调用super.updateItem(...)
  • 您可以在updateItem实现中调用setItem(...)和setEmpty(...),并在检查和编辑内容中“旁路”ListCell实现

请注意,ListCell它不是ListView使用的“基础”实现。请参阅TextFieldListCell类,它是一个很好的例子,它实际上是如何工作的,从mercurial和read中获取源代码,它始终是最好的方法。

例如,TextFieldListCell使用super.updateItem(...)来调用Cell.updateItem实现以检查它是否为空(通过使用setItem或setEmpty),然后使用javafx.scene.control.cell.CellUtils。的updateItem(...)。此方法获取在当前单元格中设置的项目,然后在项目上使用转换器以在标签中显示字符串。

答案 1 :(得分:2)

ListCell的默认实现执行一些标准的内务处理。例如,它注册了一个鼠标监听器,可以适当地更新ListView的选择模型。

super.updateItem(...)调用调用该方法的超类实现。如果省略它,那么选择就不会起作用,并且可能还有很多其他功能也无法正常工作。

在您的代码中,lastItem字段是多余的。已经在ListCell类中定义了item属性:updateItem(...)的默认实现所做的另一个工作是更新此属性。因此,您可以省略该字段,只需在需要获取项目时调用getItem()

忘记拨打super.updateItem(...)很容易。出于这个原因,我经常使用另一种方法:

mpcListView.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
    @Override
    public ListCell<String> call(ListView<String> param){
        return createXCell();
    }
});

public ListCell<String> createXCell() {
    final ListCell<String> cell = new ListCell<String>();
    final HBox hbox = new HBox();
    final Label label = new Label();
    final Button button = new Button("",getImage());

    hbox.setSpacing(120);
    hbox.getChildren().addAll(label,button);
    button.setOnAction(new EventHandler<ActionEvent>(){
    @Override
        public void handle(ActionEvent event){
            mpcListView.getItems().remove(cell.getItem());
        }
    });

    cell.itemProperty().addListener(new ChangeListener<String>() {
        @Override
        public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
            if (newValue == null) {
                cell.setText(null);
                cell.setGraphic(null);
            } else {
                cell.setText(newValue);
                cell.setGraphic(hbox);
            }
        }
    });

    return cell ;

}

请注意,我根本没有对ListCell进行子类化:我只使用默认实现,并使用itemProperty上的侦听器更新文本和图形。这更符合&#34;更喜欢继承和#34;。

的精神