具有自定义对象的

时间:2016-01-17 12:33:27

标签: java listview javafx custom-cell

我正在尝试根据自定义ListView列表制作由自定义Cell组成的自定义objects

自定义对象是名为Message的类名,其中包含消息内容收件人时间戳的几个字段以及状态(阅读,发送等)。

看了这个问题:Customize ListView in JavaFX with FXML我成功了:

  1. 使用自定义单元格创建了一个ListView,其中单元格设计在 FXML文件中定义;
  2. 关联控制器,以便每个单元格数据都可以使用该集合的当前项填充;
  3. 但是,我无法将两者联系起来:我似乎无法找到方法,以便将ListView的当前项目发送到 Cell Controller

    这是我的单元工厂代码和ListView项目填充:

    final ObservableList observableList = FXCollections.observableArrayList();
    observableList.setAll(myMessages); //assume myMessage is a ArrayList<Message>
    conversation.setItems(observableList); //the listview
    conversation.setCellFactory(new Callback<ListView<Message>, ListCell<Message>>() {
        @Override
        public ConversationCell<Message> call(ListView<Message> listView) {
            return new ConversationCell();
        }
    });
    

    现在,ConversationCell类:

    public final class ConversationCell<Message> extends ListCell<Message> { 
    
        @Override
        protected void updateItem(Message item, boolean empty) {
            super.updateItem(item, empty);
            ConversationCellController ccc = new ConversationCellController(null);
            setGraphic(ccc.getView());
        }
    }
    

    我无法显示ConversationCellController,但我可以说,这是(在其构造函数中)我加载设计单元格的FXML文件,然后我可以用给定的Message项填充值。

    getView()方法返回根窗格,其中包含现已填充并设计的单元格。

    正如我之前所说,设计工作,但我似乎无法将ListView项目与 CellFactory 相关联,因为在方法中

      

    protected void updateItem(消息项,布尔值为空)

    设置为 true ,项目确实 null

    我可以做些什么来完成这项工作?

1 个答案:

答案 0 :(得分:12)

覆盖updateItem(...)的所有自定义单元格实现都需要处理该方法中单元格为空的情况。所以你可以用

做一个天真的解决方案
public final class ConversationCell<Message> extends ListCell<Message> { 

    @Override
    protected void updateItem(Message item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setGraphic(null);
        } else {
            // did you mean to pass null here, or item??
            ConversationCellController ccc = new ConversationCellController(null);
            setGraphic(ccc.getView());
        }
    }
}

然而,从性能的角度来看,这不是一个好的解决方案。每次使用非空单元格调用updateItem(...)时都会加载FXML,这是一项非常昂贵的操作(可能涉及文件i / o,从jar文件解压缩FXML文件,解析文件,很多反射,创建新的UI元素等)。每次用户滚动列表视图几个像素时,您都不希望FX应用程序线程执行所有工作。相反,您的单元格应缓存节点,并应使用updateItem方法更新它:

public final class ConversationCell<Message> extends ListCell<Message> { 

    private final ConversationCellController ccc = new ConversationCellController(null);
    private final Node view = ccc.getView();

    @Override
    protected void updateItem(Message item, boolean empty) {
        super.updateItem(item, empty);
        if (empty) {
            setGraphic(null);
        } else {
            ccc.setItem(item);
            setGraphic(view);
        }
    }
}

您应该在setItem(...)中定义ConversationCellController方法,以便相应地更新视图(在标签上设置文本等)。