当对象是类型时,在tableview上显示图像 [英] Display image on tableview when object is of a type
问题描述
首先,对不起我的英语并感谢您阅读..: - )
我有一个tableview,它显示了一个名为Produto的类的信息。 / p>
该表有一列显示一个名为produto的图像,但我只需要为某种类型的Produto显示此图像。
Produto类:
public class Produto {
private整数id;
private String nome;
私人Tipo型;
//设置..
}
表格列:
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()。getRes ourceAsStream( 16x16.png)));
box.getChildren()。addAll(imageview,vbox);
setGraphic(方框);
}
}
};
返回单元格;
}
});
如何访问updateItem中的当前Produto对象,获取Produto的类型并选择是否显示或不显示表格上的图像?
我通常采用的方法是使表格列的类型为与表格类型相同:
TableColumn< Produto,Produto> tbcNomeProduto = new TableColumn<>();
原因是此列中单元格中显示的值取决于两件事: code> Produto.nome 和 Produto.type
;换句话说,此列中的单元格是 Produto.nome
和 Produto.type
的视图。因此,包含显示单元格所需的所有数据的最小实体(即单元格所在的最小实体)是 Produto
实例本身。
所以现在我会这样做
tbcNomeProduto.setCellValueFactory(新的回调< CellDataFeatures< Produto, Produto>,ObservableValue< Produto>>(){
@Override
public ObservableValue< Produto> call(CellDataFeatures< Produto,Produto> data){
返回新的ReadOnlyObjectWrapper<>(数据.getValue());
}
});
tbcNomeProduto.setCellFactory(new Callback< TableColumn< Produto,Produto>,TableCell< Produto,Produto>>(){
@Override
public TableCell< Produto,Produto> call(TableColumn< Produto,Produto> col){
返回新的TableCell< Produto,Produto>(){
private HBox hbox = new HBox();
private ImageView imageView = new ImageView( new Image(getClass()。getResourceAsStream(16x16.png)));
private Label label = new Label();
//匿名构造函数:
{
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(/ *应该显示图像... * /){
hbox.getChildren()。add(imageView);
}
hbox.getChildren()。add(label);
}
}
};
}
});
在您的示例中,您的 Produto
类是一个POJO,遵循标准的JavaBean约定,而不使用可观察的JavaFX属性。因此,如果要为显示的 Produto
实例更改 nome
字段,则表格无法更新无论如何,因为 nome
字段是不可观察的。
如果你在<$ c中有可观察的字段$ c> 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);
}
私人最终ObjectProperty< Tipo> type = new SimpleObjectProperty<>();
// get / set和属性访问器方法如上所示....
private final IntegerProperty id = new SimpleIntegerProperty();
//获取/设置和属性访问方法...
}
如上所述,你有
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<>();
// nome属性更改的监听器:
ChangeListener< String> nomeListener =(obs,oldNome,newNome) - > label.setText(newNome);
//类型属性更改的侦听器:
ChangeListener< Tipo> typeListener =(obs, oldType,newType) - > {
if(/ *应该显示图像* /){
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(/ *应显示图形* /){
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);
返回单元格;
});
这可以很容易地在不同条件下显示不同的图像,甚至可以操作单元格的css样式等等。
First of all, sorry my english and thanks for reading.. :-)
I have a tableview and it show some information about a class named Produto.
The table has a column where is displayed a image with the name of produto, but I need to show this image only for some type of Produto.
The Produto class:
public class Produto {
private Integer id;
private String nome;
private Tipo type;
//get set..
}
The column of table:
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;
}
});
How could I access the current Produto object inside the updateItem, to get the type of Produto and choose if display or not the image on the table?
The way I usually approach this is to make the type of the table column the same as the type of the table:
TableColumn<Produto, Produto> tbcNomeProduto = new TableColumn<>();
The reason for this is that the value displayed in the cells in this column depends on two things: Produto.nome
and Produto.type
; in other words the cells in this column are views of both Produto.nome
and Produto.type
. Thus the smallest entity containing all the data needed to display the cell (i.e. the smallest entity of which the cell is a view) is the Produto
instance itself.
So now I would do
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);
}
}
};
}
});
In your example, your Produto
class is a POJO, following the standard JavaBean conventions and not using observable JavaFX Properties. Thus if the nome
field were to change for a displayed Produto
instance, there would be no opportunity for the table to update anyway, as the nome
field is not observable.
If you were to have observable fields in the Produto
class, and those values could change while the object was displayed, then you would need to do a bit more work in the table cell. This is because the nome
field could change without the Produto
instance changing; the latter means that the updateItem(...)
method would not be invoked. I want to include the code to manage this for other readers who may come across this question, even though it's not relevant for the question at hand. Using anonymous inner classes for this gets very ugly in a hurry, so I'm going to revert to Java 8 code and use lambda expressions for this section.
So suppose the Produto
class looks like
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...
}
As above you have
TableColumn<Produto, Produto> tbcNomeProduto = new TableColumn<>();
tbcNomeProduto.setCellValueFactory(cellData -> new ReadOnlyPropertyWrapper<>(cellData.getValue()));
For the cell factory, you need to create listeners for the individual properties. Register and deregister those properties when the Produto
that is displayed changes:
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 ;
});
This generalizes fairly easily to display different images under different conditions, or even to manipulate css styles for the cell, etc.
这篇关于当对象是类型时,在tableview上显示图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!