如何在TableView中正确设置图像



我试图用ImageView作为其值之一的对象填充表视图,但表视图中只有最后一项显示图像,其余项都不执行

public class MainController implements Initializable {
public TableView<Apple> table;
public TableColumn nameColumn;
public TableColumn imageColumn;
ImageView imageView = new ImageView(new Image("download.jpg"));
Apple apple = new Apple("Bob",imageView);
Apple apple2 = new Apple("John",imageView);
Apple[] apples = {apple2,apple};
List<Apple> appleList = Arrays.asList(apples);

@Override
public void initialize(URL location, ResourceBundle resources) {
imageColumn.setCellValueFactory(new PropertyValueFactory<>("image"));
nameColumn.setCellValueFactory((new PropertyValueFactory<>("name")));
table.setItems(FXCollections.observableArrayList(appleList));
}
}

public class Apple {
private final int SIZE = 20;
String name;
ImageView image;
public Apple(String name, ImageView image) {
this.name = name;
this.image = image;
image.setFitHeight(SIZE);
image.setFitWidth(SIZE);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ImageView getImage() {
return image;
}
public void setImage(ImageView image) {
this.image = image;
}
}

我不知道为什么会发生这种情况,我看到人们在网上使用循环设置图像1比1。

正如@jewelsea在评论中所说,您的模型类(Apple(应该只包含数据;它不应该包含诸如CCD_ 2之类的UI字段。任何Node在场景图中只能出现一次,这就是为什么您只能在表中的单行中看到ImageView

您应该将图像的路径或Image(它只是数据(本身存储在模型类中。这两种选择之间的权衡是计算时间与内存消耗的权衡。如果存储图像的路径,则每次单元格更新时(例如在滚动期间(都需要加载图像,这需要时间。另一方面,如果存储Image,那么整个表所需的所有图像都需要存储在内存中,无论它们是否显示。

如果表只需要少量图像,我建议将Image存储在模型类中。如果表只有几行,或者有少量图像,并且多行显示同一图像,则可能会发生这种情况。请注意,Images可以由多个ImageViews共享,因此不需要多次加载任何单个Image

在模型类中使用Image如下所示:

public class Apple {
private String name;
private Image image;
public Apple(String name, Image image) {
this.name = name;
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Image getImage() {
return image;
}
public void setImage(Image image) {
this.image = image;
}
}

您将需要一个单元格实现来显示图像:

public class ImageCell extends TableCell<Apple, Image> {
private static final IMAGE_SIZE = 20 ;
private final ImageView imageView ;
public TableCell() {
imageView = new ImageView();
imageView.setFitWidth(IMAGE_SIZE);
imageView.setFitHeight(IMAGE_SIZE);
imageView.setPreserveRatio(true);
}
@Override
protected void updateItem(Image image, boolean empty) {
if (empty || item == null) {
setGraphic(null);
} else {
imageView.setImage(image);
setGraphic(imageView);
}
}
}

您的应用程序代码看起来像:

public class MainController implements Initializable {
public TableView<Apple> table;
public TableColumn<Apple, String> nameColumn;
public TableColumn<Apple, Image> imageColumn;
Image downloadImage = new Image("download.jpg");
Apple apple = new Apple("Bob",downloadImage);
Apple apple2 = new Apple("John",downloadImage);

@Override
public void initialize(URL location, ResourceBundle resources) {
imageColumn.setCellValueFactory(cellData -> new SimpleObjectProperty<>(cellData.getValue().getImage()));
imageColumn.setCellFactory(column -> new ImageCell());
nameColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getName()));
table.setItems(FXCollections.observableArrayList(apple2, apple));
}
}

如果表中有大量不同的图像,这可能不太可能,那么应该在模型类中表示图像的路径:

public class Apple {
private String name;
private String imagePath;
public Apple(String name, String imagePath) {
this.name = name;
this.imagePath = imagePath;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImagePath() {
return imagePath;
}
public void setImage(String imagePath) {
this.imagePath = imagePath;
}
}

然后你的手机类需要加载图像:

public class ImageCell extends TableCell<Apple, String> {
private static final IMAGE_SIZE = 20 ;
private final ImageView imageView ;
public TableCell() {
imageView = new ImageView();
imageView.setFitWidth(IMAGE_SIZE);
imageView.setFitHeight(IMAGE_SIZE);
imageView.setPreserveRatio(true);
}
@Override
protected void updateItem(String imagePath, boolean empty) {
if (empty || item == null) {
setGraphic(null);
} else {
imageView.setImage(new Image(imagePath));
setGraphic(imageView);
}
}
}

您的应用程序代码有明显的修改:

public class MainController implements Initializable {
public TableView<Apple> table;
public TableColumn<Apple, String> nameColumn;
public TableColumn<Apple, String> imageColumn;
Apple apple = new Apple("Bob", "download.jpg");
Apple apple2 = new Apple("John", "download.jpg");

@Override
public void initialize(URL location, ResourceBundle resources) {
imageColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getImagePath()));
imageColumn.setCellFactory(column -> new ImageCell());
nameColumn.setCellValueFactory(cellData -> new SimpleStringProperty(cellData.getValue().getName()));
table.setItems(FXCollections.observableArrayList(apple2, apple));
}
}

最新更新