有时,一列应该显示的内容不仅仅是toString单元格项目的值。在这种情况下,由TableCell的创建cellFactory的会TableColumn被自定义,以根据项目更改布局。
重要说明: TableView仅创建TableCellUI中显示的。单元格内的项目可以更改,甚至变空。程序员需要注意撤消TableCell对删除项的添加所做的任何更改。否则,内容可能仍会显示在“不属于”的单元格中。
在以下示例中,设置项目会导致设置文本以及显示在中的图像ImageView:
image.setImage(item.getEmoji()); setText(item.getValue());
如果该项变为null或单元格为空,则通过将值设置回以下来撤消那些更改null:
setText(null); image.setImage(null);
以下示例显示了中除文字外的表情符号TableCell。
updateItem每次Cell更改a的项目时都会调用此方法。重写此方法可以对更改做出反应并调整单元格的外观。将侦听器添加到itemProperty()单元的可以是一种替代方法,但是在许多情况下TableCell可以扩展。
物品种类
import javafx.scene.image.Image; // 枚举提供某些感觉的图像和文本 public enum Feeling { HAPPY("happy", "https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Emojione_1F600.svg/64px-Emojione_1F600.svg.png"), SAD("sad", "https://upload.wikimedia.org/wikipedia/commons/thumb/4/42/Emojione_1F62D.svg/64px-Emojione_1F62D.svg.png") ; private final Image emoji; private final String value; Feeling(String value, String url) { // 在背景中加载图片 emoji = new Image(url, true); this.value= value; } public Image getEmoji() { return emoji; } public String getValue() { return value; } }
应用程序类中的代码
import javafx.application.Application; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.collections.FXCollections; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.TableCell; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.util.Callback; public class EmotionTable extends Application { public static class Item { private final ObjectProperty<Feeling> feeling; public Item(Feeling feeling) { this.feeling= new SimpleObjectProperty<>(feeling); } public final Feeling getFeeling() { return this.feeling.get(); } public final void setFeeling(Feeling value) { this.feeling.set(value); } public final ObjectProperty<Feeling> feelingProperty() { return this.feeling; } } @Override public void start(Stage primaryStage) { TableView<Item> table = new TableView<>(FXCollections.observableArrayList( new Item(Feeling.HAPPY), new Item(Feeling.HAPPY), new Item(Feeling.HAPPY), new Item(Feeling.SAD), null, new Item(Feeling.HAPPY), new Item(Feeling.HAPPY), new Item(Feeling.SAD) )); EventHandler<ActionEvent> eventHandler = new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { // 根据源用户数据更改表项 Node source = (Node) event.getSource(); Feeling targetFeeling = (Feeling) source.getUserData(); for (Item item : table.getItems()) { if (item != null) { item.setFeeling(targetFeeling); } } } }; TableColumn<Item, Feeling> feelingColumn = new TableColumn<>("Feeling"); feelingColumn.setCellValueFactory(new PropertyValueFactory<>("feeling")); // 使用自定义表格单元格显示表情符号图像 feelingColumn.setCellFactory(new Callback<TableColumn<Item, Feeling>, TableCell<Item, Feeling>>() { @Override public TableCell<Item, Feeling> call(TableColumn<Item, Feeling> param) { return new EmojiCell<>(); } }); table.getColumns().add(feelingColumn); Button sunshine = new Button("sunshine"); Button rain = new Button("rain"); sunshine.setOnAction(eventHandler); rain.setOnAction(eventHandler); sunshine.setUserData(Feeling.HAPPY); rain.setUserData(Feeling.SAD); Scene scene = new Scene(new VBox(10, table, new HBox(10, sunshine, rain))); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
单元类别
import javafx.scene.control.TableCell; import javafx.scene.image.ImageView; public class EmojiCell<T> extends TableCell<T, Feeling> { private final ImageView image; public EmojiCell() { // 将ImageView添加为图形以显示它 // 到单元格中的文本 image = new ImageView(); image.setFitWidth(64); image.setFitHeight(64); image.setPreserveRatio(true); setGraphic(image); setMinHeight(70); } @Override protected void updateItem(Feeling item, boolean empty) { super.updateItem(item, empty); if (empty || item == null) { // 回到空单元格的外观 setText(null); image.setImage(null); } else { // 为非空单元格设置图像和文本 image.setImage(item.getEmoji()); setText(item.getValue()); } } }