首先,对不起我的英语,感谢您阅读..: - )
我有一个tableview,它显示了一个名为Produto的类的信息。
该表有一列显示一个名为produto的图像,但我只需要为某种类型的Produto显示此图像。
Produto课程:
public class Produto {
private Integer id;
private String nome;
private Tipo type;
//get set..
}
表格列:
TableColumn<Produto,String> tbcNomeProduto = new TableColumn<Produto,String>();
tbcNomeProduto.setCellValueFactory(new PropertyValueFactory<Produto, String>("nome"));
tbcNomeProduto.setCellFactory(new Callback<TableColumn<Produto,String>,TableCell<Produto,String>>(){
@Override
public TableCell<Produto, String> call(TableColumn<Produto, String> param) {
TableCell<Produto, String> cell = new TableCell<Produto, String>(){
@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的类型并选择是否显示表格中的图像?
答案 0 :(得分:1)
我通常采用的方法是使表列的类型与表的类型相同:
TableColumn<Produto, Produto> tbcNomeProduto = new TableColumn<>();
原因是此列中单元格中显示的值取决于两件事:Produto.nome
和Produto.type
;换句话说,此列中的单元格是Produto.nome
和Produto.type
的视图。因此,包含显示单元格所需的所有数据的最小实体(即单元格是视图的最小实体)是Produto
实例本身。
所以现在我会做
tbcNomeProduto.setCellValueFactory(new Callback<CellDataFeatures<Produto, Produto>, ObservableValue<Produto>>() {
@Override
public ObservableValue<Produto> call(CellDataFeatures<Produto, Produto> data) {
return new ReadOnlyObjectWrapper<>(data.getValue());
}
});
tbcNomeProduto.setCellFactory(new Callback<TableColumn<Produto, Produto>, TableCell<Produto, Produto>>() {
@Override
public TableCell<Produto, Produto> call(TableColumn<Produto, Produto> col) {
return new TableCell<Produto, Produto>() {
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属性。因此,如果要为显示的nome
实例更改Produto
字段,则无论如何都无法更新表,因为nome
字段无法观察。
如果你在Produto
类中有可观察的字段,并且在显示对象时这些值可能会发生变化,那么你需要在表格单元格中做更多的工作。这是因为nome
字段可能会在Produto
实例没有更改的情况下发生变化;后者意味着不会调用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<Tipo> type = new SimpleObjectProperty<>() ;
// get/set and property accessor methods as above....
private final IntegerProperty id = new SimpleIntegerProperty();
// get/set and property accessor methods...
}
如上所述
TableColumn<Produto, Produto> 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<Produto, Produto> cell = new TableCell<>();
// listener for the nome property changing:
ChangeListener<String> nomeListener = (obs, oldNome, newNome) -> label.setText(newNome);
// listener for type property changing:
ChangeListener<Tipo> 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样式等。