JavaFX ListView使用cellfactory更新选定的单元格视图
在这里,我使用cellfactory创建了一个自定义listview,并使用自定义节点进行了更新,但我需要在选择单元格时更改图形(内容)。我知道我们使用css来改变所选单元格的外观,但是在这里我想更新listview中所选单元格的图形(内容),而不是背景色或文本颜色。有没有这样的方法 通常我的listview层次结构是这样的 Hbox->Label1、Label2 但当我选择任何单元格时,它应该(仅选择的单元格)如下更新 Hbox->Label1、Label2、label3、Label4、按钮1 这是我的密码JavaFX ListView使用cellfactory更新选定的单元格视图,listview,javafx,cell,Listview,Javafx,Cell,在这里,我使用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的人来说非常有用(不是展开它,而是更新选择项上的内容,例如:通常它只显示项名称,如果您选择了任何单元格,则表示它将显示项名称、价格等)@ihsanikballist.setAll(someElements);
与list.clear();list.addAll(someElements);
具有相同的效果,但它只触发一次更新。。。