当对象是类型时,在tableview上显示图像

首先,对不起我的英语,感谢阅读.. 🙂

我有一个tableview,它显示了一个名为Produto的类的一些信息。

该表有一列显示一个名为produto的图像,但我只需要为某种类型的Produto显示此图像。

Produto类:

public class Produto { private Integer id; private String nome; private Tipo type; //get set.. } 

表格列:

 TableColumn tbcNomeProduto = new TableColumn(); tbcNomeProduto.setCellValueFactory(new PropertyValueFactory("nome")); tbcNomeProduto.setCellFactory(new Callback<TableColumn,TableCell>(){ @Override public TableCell call(TableColumn param) { TableCell cell = new TableCell(){ @Override public void updateItem(String item, boolean empty) { if(item != null){ HBox box= new HBox(); box.setSpacing(10); VBox vbox = new VBox(); vbox.getChildren().add(new Label(item)); ImageView imageview = new ImageView(); imageview.setImage(new Image(getClass().getResourceAsStream("16x16.png"))); box.getChildren().addAll(imageview,vbox); setGraphic(box); } } }; return cell; } }); 

我如何访问updateItem中的当前Produto对象,以获取Produto的类型并选择是否显示表格上的图像?

我通常采用的方法是使表列的类型与表的类型相同:

 TableColumn tbcNomeProduto = new TableColumn<>(); 

原因是此列中单元格中显示的值取决于两件事: Produto.nomeProduto.type ; 换句话说,此列中的单元格是Produto.nomeProduto.type 。 因此,包含显示单元所需的所有数据的最小实体(即,单元是视图的最小实体)是Produto实例本身。

所以现在我会这样做

 tbcNomeProduto.setCellValueFactory(new Callback, ObservableValue>() { @Override public ObservableValue call(CellDataFeatures data) { return new ReadOnlyObjectWrapper<>(data.getValue()); } }); tbcNomeProduto.setCellFactory(new Callback, TableCell>() { @Override public TableCell call(TableColumn col) { return new TableCell() { private HBox hbox = new HBox(); private ImageView imageView = new ImageView(new Image(getClass().getResourceAsStream("16x16.png"))); private Label label = new Label(); // anonymous constructor: { setGraphic(hbox); setContentDisplay(ContentDisplay.GRAPHIC_ONLY); } @Override public void updateItem(Produto item, boolean empty) { super.updateItem(item, empty); hbox.getChildren().clear(); if (item != null) { Tipo type = item.getType(); String nome = item.getNome(); if (/* should show image...*/) { hbox.getChildren().add(imageView); } hbox.getChildren().add(label); } } }; } }); 

在您的示例中,您的Produto类是POJO,遵循标准JavaBean约定而不使用可观察的JavaFX属性。 因此,如果要为显示的Produto实例更改nome字段,则无论如何都无法更新表,因为nome字段不可观察。

如果你在Produto类中有可观察的字段,并且在显示对象时这些值可能会改变,那么你需要在表格单元格中做更多的工作。 这是因为在没有Produto实例更改的情况下, nome字段可能会更改; 后者意味着不会调用updateItem(...)方法。 我希望包含代码来管理可能遇到此问题的其他读者,即使它与手头的问题无关。 为此使用匿名内部类会非常难看,所以我将恢复到Java 8代码并在本节中使用lambda表达式。

所以假设Produto类看起来像

 public class Produto { private final StringProperty nome = new SimpleStringProperty(); public StringProperty nomeProperty() { return nome ; } public final String getNome() { return nomeProperty().get(); } public final void setNome(String nome) { nomeProperty().set(nome); } private final ObjectProperty type = new SimpleObjectProperty<>() ; // get/set and property accessor methods as above.... private final IntegerProperty id = new SimpleIntegerProperty(); // get/set and property accessor methods... } 

如上所述

 TableColumn tbcNomeProduto = new TableColumn<>(); tbcNomeProduto.setCellValueFactory(cellData -> new ReadOnlyPropertyWrapper<>(cellData.getValue())); 

对于单元工厂,您需要为各个属性创建侦听器。 当显示的Produto发生变化时,注册并取消注册这些属性:

 tbc.setCellFactory(col -> { Label label = new Label(); ImageView imageView = new ImageView(new Image(getClass().getResourceAsStream("16x16.png"))); HBox hbox = new HBox(); TableCell cell = new TableCell<>(); // listener for the nome property changing: ChangeListener nomeListener = (obs, oldNome, newNome) -> label.setText(newNome); // listener for type property changing: ChangeListener typeListener = (obs, oldType, newType) -> { if ( /* should show image */) { hbox.getChildren().setAll(imageView, label); } else { hbox.getChildren().setAll(label); } } cell.itemProperty().addListener((obs, oldProduto, newProduto) -> { if (oldProduto != null) { oldProduto.nomeProperty().removeListener(nomeListener); oldProduto.typeProperty().removeListener(typeListener); } if (newProduto == null) { cell.setGraphic(null); } else { label.setText(newProduto.getNome()); Tipo type = newProduto.getType(); if (/* should show graphic */) { hbox.getChildren().setAll(imageView, label); } else { hbox.getChildren().setAll(label); } cell.setGraphic(hbox); newProduto.nomeProperty().addListener(nomeListener); newProduto.typeProperty().addListener(typeListener); } }); cell.setContentDisplay(ContentDisplay.GRAPHIC_ONLY); return cell ; }); 

这很容易概括地在不同条件下显示不同的图像,甚至可以操纵单元格的css样式等。