JavaFX ListView使用cellfactory更新选定的单元格视图

JavaFX ListView使用cellfactory更新选定的单元格视图,listview,javafx,cell,Listview,Javafx,Cell,在这里,我使用cellfactory创建了一个自定义listview,并使用自定义节点进行了更新,但我需要在选择单元格时更改图形(内容)。我知道我们使用css来改变所选单元格的外观,但是在这里我想更新listview中所选单元格的图形(内容),而不是背景色或文本颜色。有没有这样的方法 通常我的listview层次结构是这样的 Hbox->Label1、Label2 但当我选择任何单元格时,它应该(仅选择的单元格)如下更新 Hbox->Label1、Label2、label3、Label4、按钮1

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

通常我的listview层次结构是这样的

Hbox->Label1、Label2

但当我选择任何单元格时,它应该(仅选择的单元格)如下更新

Hbox->Label1、Label2、label3、Label4、按钮1

这是我的密码

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);
回调cellFactory=new Callback() { @凌驾 公共ListCell调用(ListView arg0) { 单元格=新的ListCell() { @凌驾 受保护的void updateItem(CustomListView项,布尔bln) { super.updateItem(项目,bln); 如果(项==null) { 设置图形(空); setText(空); 返回; } 其他的 { //通常情况下,我的listview将显示如下(带有2个标签的HBOX) HBox h1=新的HBox(); 标签项目名称=新标签(“项目1”); 标签价格=新标签(“100”); h1.getchildren.addAll(项目名称、价格); 设定图形(h1); //当我选择任何单元格时,它应该显示如下((一个带有4个标签的Hbox(仅选定单元格,其余单元格为第一种格式)) HBox h2=新的HBox(); 标签项目名称=新标签(“项目1”); 标签价格=新标签(“100”); 标签折扣=新标签(“50%”); 标签税=新标签(“5%”); 按钮b1=新按钮(); h2.getchildren.addAll(项目名称、价格、折扣、税、b1); 设定图形(h2); //我尝试过这些代码行,但它不能正常工作 cell.selectedProperty().addListener((obs、wasSelected、isNowSelected)->{ if(isNowSelected==false)//未选择 { //加载hbox1 } else//selected { //负载hbox2 } } } }返回单元; } }; setCellFactory(cellFactory);
首先,
单元格
用于在显示不同项目时防止不必要的节点创建。因此,您不应在每次调用
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);
        }
    }

});
listView.setCellFactory(l->new ListCell()){
//创建可以显示的所有节点
专用最终标签itemName=新标签(“item1”);
私人最终标签价格=新标签(“100”);
私有最终HBox contentContainer=新HBox();
私人最终标签折扣=新标签(“50%”);
私人最终标签税=新标签(“5%”);
私有最终按钮=新按钮();
{
//每次选择更改时更新HBox
selectedProperty().addListener((可观察、旧值、新值)->{
CustomListView项=getItem();
如果(!isEmpty()&&item!=null){
updateItemSelection(项目,新值);
}
});
}
@凌驾
受保护的void updateItem(CustomListView项,布尔值为空){
super.updateItem(项,空);
if(空| |项==null){
设置图形(空);
}否则{
设置图形(内容容器);
updateItemSelection(项,isSelected());
}
}
private void updateItemSelection(CustomListView项,布尔值选中){
//根据选择更新非空单元格的HBox
如果(选定){
contentContainer.getChildren().setAll(项目名称、价格、折扣、税收、按钮);
}否则{
contentContainer.getChildren().setAll(itemName,price);
}
}
});

请阅读并采取相应行动:)是的,它成功了。我的代码中的错误是因为我刚刚修改成了可以理解的方式。谢谢fabian,你是我的英雄。你能告诉我hbox.getchildren.addAll和hbox.getchildren.setAll之间的区别吗?正如你在代码中提到的。谢谢。这段代码对于那些在javafx中寻找可扩展listview的人来说非常有用(不是展开它,而是更新选择项上的内容,例如:通常它只显示项名称,如果您选择了任何单元格,则表示它将显示项名称、价格等)@ihsanikbal
list.setAll(someElements);
list.clear();list.addAll(someElements);
具有相同的效果,但它只触发一次更新。。。