有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

首先,对不起我的英语,谢谢你的阅读

我有一个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的类型并选择是否显示表上的图像


共 (1) 个答案

  1. # 1 楼答案

    我通常的做法是使表列的类型与表的类型相同:

    TableColumn<Produto, Produto> tbcNomeProduto = new TableColumn<>();
    

    原因是,此列中单元格中显示的值取决于两件事:Produto.nomeProduto.type;换句话说,此列中的单元格是Produto.nomeProduto.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属性。因此,如果为显示的Produto实例更改nome字段,则无论如何都没有机会更新表,因为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样式,等等