根据项目自定义 TableCell 外观
有时,列应显示的内容与单元格项的 toString 值不同。在这种情况下,由 TableColumn 的 cellFactory 创建的 TableCells 被定制以根据项目改变布局。
重要说明: TableView 仅创建 UI 中显示的 TableCells。单元格内的项目可以更改甚至变空。程序员需要注意撤消对 TableCell 的任何更改,这些更改是在删除项目时添加的。否则,内容仍可能显示在它不属于的单元格中。
在下面的示例设置中,项目将导致设置的文本以及 ImageView 中显示的图像:
image.setImage(item.getEmoji());
setText(item.getValue());
如果项目变为 null 或单元格变空,则通过将值设置回 null 来撤消这些更改:
setText(null);
image.setImage(null);
以下示例显示了除 TableCell 中的文本之外的表情符号。
每次改变 Cell 的项目时都会调用 updateItem 方法。覆盖此方法可以对更改做出反应并调整单元格的外观。将监听器添加到单元的 itemProperty() 将是另一种选择,但在许多情况下,TableCell 被扩展。
物品种类
import javafx.scene.image.Image;
// enum providing image and text for certain feelings
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) {
        // load image in background
        emoji = new Image(url, true);
        this.value = value;
    }
    public Image getEmoji() {
        return emoji;
    }
    public String getValue() {
        return value;
    }
    
}
Application 类中的代码
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) {
                // change table items depending on userdata of source
                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"));
        // use custom tablecell to display emoji image
        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() {
        // add ImageView as graphic to display it in addition
        // to the text in the cell
        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) {
            // set back to look of empty cell
            setText(null);
            image.setImage(null);
        } else {
            // set image and text for non-empty cell
            image.setImage(item.getEmoji());
            setText(item.getValue());
        }
    }
}