当对象是类型时,在tableview上显示图像 [英] Display image on tableview when object is of a type

查看:139
本文介绍了当对象是类型时,在tableview上显示图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,对不起我的英语并感谢您阅读..: - )



我有一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆