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