JavaFX ListView - 使用cellfactory

时间:2017-10-09 07:32:07

标签: listview javafx cell

这里我使用cellfactory创建了一个自定义列表视图并使用自定义节点进行了更新,但是当我选择一个单元格时,我需要更改图形(内容)。我知道我们使用css来改变所选单元格的外观,但在这里我想更新listview中所选单元格的图形(内容)而不是背景颜色或文本颜色。有什么方法可以做该??

通常我的listview层次结构就像这样

Hbox-> Label1的,Label2的

但是当我选择任何一个单元格时,它应该(仅选择单元格)像这样更新

Hbox-> Label1的,Label2的,Labe3,Label4,Button1的

这是我的代码

Callback<ListView<CustomListView>, ListCell<CustomListView>> cellFactory = new Callback<ListView<CustomListView>, ListCell<CustomListView>>() 
{ 

    @Override
        public ListCell<CustomListView> call(ListView<CustomListView> arg0) 
    {

        cell = new ListCell<CustomListView>() 
        {

                @Override
                protected void updateItem(CustomListView item, boolean bln) 
            {

                super.updateItem(item, bln);
                            if(item == null)
                            {
                                setGraphic(null);
                                setText(null);
                                return;
                            }
                            else
                {
                    //Normally my listview will display like this(An HBOX with 2 Labels)

                    HBox h1 =new HBox();
                    Label itemName=new Label("item1);
                    Label price=new Label("100");
                    h1.getchildren.addAll(itemName,price);
                    setGraphic(h1);

                    //When i select any cell it should  display like this((An Hbox with 4 Labels(selected cell only,remaining cells in first format))

                    HBox h2 =new HBox();
                    Label itemName=new Label("item1);
                    Label price=new Label("100");
                    Label Discount=new Label("50%");
                    Label Tax=new Label("5%");  
                    Button b1=new Button();
                    h2.getchildren.addAll(itemName,price,discount,tax,b1); 
                    setGraphic(h2);

                    //i have tried with these lines of codes but it does not working properly
                    cell.selectedProperty().addListener((obs, wasSelected, isNowSelected) -> {
                    if(isNowSelected==false)//not selected
                   {
                        //load hbox1
                    }
                    else //selected
                    { 
                        //load hbox2
                    }



                }
                             }
        }; return cell;
    }
};
    listView.setCellFactory(cellFactory);

1 个答案:

答案 0 :(得分:1)

首先,Cell旨在防止在显示不同项目时创建不必要的节点。因此,每次调用updateItem时都不应重新创建节点。此外,您永远不会从selected属性中删除侦听器,这意味着可能会有许多HBox更新,这些永远不再可见。您的代码中也存在一些错误,导致无法编译...

以下代码应该可以使用:

listView.setCellFactory(l -> new ListCell<CustomListView >() {

    // create all nodes that could be displayed
    private final Label itemName = new Label("item1");
    private final Label price = new Label("100");
    private final HBox contentContainer = new HBox();

    private final Label discount = new Label("50%");
    private final Label tax = new Label("5%");
    private final Button button = new Button();

    {
        // update HBox every time the selection changes
        selectedProperty().addListener((observable, oldValue, newValue) -> {
            CustomListView item = getItem();
            if (!isEmpty() && item != null) {
                updateItemSelection(item, newValue);
            }
        });
    }

    @Override
    protected void updateItem(CustomListView  item, boolean empty) {
        super.updateItem(item, empty);

        if (empty || item == null) {
            setGraphic(null);
        } else {
            setGraphic(contentContainer);
            updateItemSelection(item, isSelected());
        }
    }

    private void updateItemSelection(CustomListView item, boolean selected) {
        // update for HBox for non-empty cells based on selection
        if (selected) {
            contentContainer.getChildren().setAll(itemName, price, discount, tax, button);
        } else {
            contentContainer.getChildren().setAll(itemName, price);
        }
    }

});