【问题标题】:JavaFX CellFactory updateItem always nullJavaFX CellFactory updateItem 始终为空
【发布时间】:2016-06-01 11:44:53
【问题描述】:

我真的很难理解 JavaFX TableColumn 中的 CellFactory 和 CellValueFactory。我必须从其他人的问题中复制和修改大部分代码。我正在尝试添加一个列,该列为每个将某个布尔值设置为负值的项目显示一个图像,并为正值显示一个图像。代码在这里(复制和修改):

 TableColumn <Track,Track> coverCol = new TableColumn<>("Artwork");
        coverCol.setCellFactory(new Callback<TableColumn<Track, Track>, TableCell<Track, Track>>() {
            @Override
            public TableCell<Track, Track> call(TableColumn<Track, Track> coverCol) {
                return new TableCell<Track, Track>(){
                    final ImageView hasArtworkView = new ImageView();
                    @Override public void updateItem(final Track artworkTrack,boolean empty){
                        super.updateItem(artworkTrack,empty);
                        if(artworkTrack != null){
                            if(artworkTrack.hasCover()){
                                hasArtworkView.setImage(hasArtworkIcon);
                            }else{
                                hasArtworkView.setImage(noArtworkIcon);
                            }
                            setGraphic(hasArtworkView);
                        }else {
                            setGraphic(null);
                        }
                    }
                };

            }
        });

updateItem 类永远不会查看对象,并且它始终默认为 null。有什么我遗漏的,或者我应该以不同的方式实现吗?

跟踪类:

public class Track {
    public String fileName;
    public String trackName;
    public String artistName;
    public String albumName;
    public String filePath;
    public SimpleBooleanProperty selected;
    public BufferedImage cover;
    Tag tag;



    public Track(File f){

        selected = new SimpleBooleanProperty(true);

        AudioFile af = null;
        try {
            af = AudioFileIO.read(f);
        } catch (CannotReadException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TagException e) {
            e.printStackTrace();
        } catch (ReadOnlyFileException e) {
            e.printStackTrace();
        } catch (InvalidAudioFrameException e) {
            e.printStackTrace();
        }

        tag = af.getTag();
        fileName = f.getName();
        filePath = f.getPath();
        trackName = tag.getFirst(FieldKey.TITLE);
        artistName = tag.getFirst(FieldKey.ARTIST);
        albumName = tag.getFirst(FieldKey.ALBUM);
        Artwork artwork = tag.getFirstArtwork();

        if(hasCover()){
            try {
                cover = Images.getImage(artwork);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }


    public String getTrackName(){
        return trackName;
    }
    public String getArtistName(){
        return artistName;
    }
    public String getAlbumName(){
        return albumName;
    }
    public boolean isSelected() {return selected.getValue();}
    public ObservableValue selectedProperty(){return selected;}
    public BufferedImage getCover (){return cover;}
    public String getFileName() {
        return fileName;
    }
    public String getFilePath(){return filePath;}


    public void setTrackName(String s){trackName = s;}
    public void setArtistName(String s){artistName = s;}
    public void setAlbumName (String s){albumName = s;}
    public void setSelected (boolean b){selected.set(b);}
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public boolean hasCover(){
        return tag.hasField(FieldKey.COVER_ART);
    }
    public boolean hasTrackName(){return tag.hasField(FieldKey.TITLE);}
    public boolean hasArtistName(){return tag.hasField(FieldKey.ARTIST);}
}

【问题讨论】:

  • 你能展示你的cellValueFactoryTrack类吗?
  • @James_D 添加了 Track 类,但是没有 cellValueFactory。我想这是我的问题,但我不知道如何使用它。所有这一切对我来说完全没有意义。作为参考,我从这个线程复制代码:stackoverflow.com/questions/16360323/…
  • 单元格值工厂将行映射为要在单元格中显示的值 - 即,它确定单元格正在显示的 数据。没有单元格值工厂,就没有数据,因此单元格显示的项目将始终为空。
  • @James_D 它显示的数据是 ImageView 类型,但它应该查看的数据是布尔值。这就是让我感到困惑的地方,当显示字符串时,你不会将内存中的实际对象传递给它,而只是传递名称,它必须遵循 Java 命名约定,这永远不会给你一个错误,并且会让每个初学者都抓狂他的头。我可能对这一切了解不多,但在我看来,CellFactory 和 CellValueFactory 是设计得很糟糕的类。
  • 不,ImageView 不是数据。它是一种显示数据的方法。这是一个 非常 标准的 UI 模式,称为模型-视图-控制器。单元格值是模型,单元格是视图。忽略PropertyValueFactory:它只是您需要的Callback 的一个方便实现,它是Java 前8 天遗留下来的,当时您需要一个匿名内部类来实现回调。现在您可以使用 lambda 表达式,它不比 PropertyValueFactory 更冗长,并且是类型安全的,可以由编译器检查,不依赖命名约定等。

标签: javafx tableview


【解决方案1】:

你可以这样做:

coverCol.setCellValueFactory(data -> new ReadOnlyObjectWrapper<Track>(data.getValue()));

这将允许您将数据放入列中,然后您的单元工厂将工作。

【讨论】:

  • cellValueFactory 用于将数据放入字段中。如果您在其中放置一个对象,它将使用该对象的 toString() 方法进行渲染。如果你想用它做一些花哨的事情,那就需要 cellFactory。
  • 确认工作,现在我只需要一种格式化 cellValueFactory 的方法,因为它显示的图像未居中。
【解决方案2】:

传递给updateItem 的项目始终为空,因为您没有定义cellValueFactory。单元格值工厂决定单元格显示的数据。

由于您的列对在该行表示的项目上调用hasCover() 的结果非常感兴趣,因此将其设为TableColumn&lt;Track, Boolean&gt; 更有意义。 (单元格中表示的数据是truefalse,即Boolean。)

所以我会定义:

TableColumn<Track, Boolean> coverCol = new TableColumn<>("Artwork");
coverCol.setCellValueFactory(cellData -> new SimpleBooleanProperty(cellData.getValue().hasCover()));
coverCol.setCellFactory(tc -> new TableCell<Track, Boolean>() {

    final ImageView hasArtworkView = new ImageView();

    @Override public void updateItem(Boolean hasCover ,boolean empty){
        super.updateItem(hasCover, empty);
        if(hasCover != null){
            if(hasCover){
                hasArtworkView.setImage(hasArtworkIcon);
            }else{
                hasArtworkView.setImage(noArtworkIcon);
            }
            setGraphic(hasArtworkView);
        }else {
            setGraphic(null);
        }
    }
});

【讨论】:

  • 给我一个错误,它要求更新两个布尔项:错误的第一个参数类型。找到:'com.jri.Track',必需:'java.lang.Boolean' 少...
  • 它正在工作,您能告诉我您为修复错误所做的更改吗?这些课程上是否有资源可以帮助我避免每次需要提问和谷歌搜索时卡住创建一个新列。正如我所说,它们对我没有任何意义,而且我总是遇到奇怪的错误,就像在我尝试像你一样定义 CellFactory 时问这个问题之前
  • This tutorial 似乎相当受欢迎。修复只是将第一个参数的类型更改为updateItem,从Track 更改为Boolean(我相应地更改了名称以使其更有意义)。
  • 谢谢,我一定会阅读的。可能明天在我的下一个 JavaFX 问题上见:D
猜你喜欢
  • 2018-09-19
  • 2017-09-12
  • 1970-01-01
  • 2018-12-24
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 2019-11-22
相关资源
最近更新 更多