当对象是类型时,在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.nome
和Produto.type
; 换句话说,此列中的单元格是Produto.nome
和Produto.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样式等。