JavaFX 2 TableView:根据单元格内的数据不同的单元格工厂 [英] JavaFX 2 TableView : different cell factory depending on the data inside the cell

查看:21
本文介绍了JavaFX 2 TableView:根据单元格内的数据不同的单元格工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用表视图来呈现/编辑键 = 值"对.所以该表应该有两列:键"和值".Key 只是一个普通的字符串,而 value 可以是任何东西.我的问题是值的数据类型可能因行而异.基本上,我想使用布尔值的复选框和列表的选择.我找到了一种通过设置单元工厂来呈现带有复选框或选项的整个表格列的方法:

I am trying to use the table view to render / edit the "key = value" pairs. So the table is supposed to have two columns : "key" and "value". Key is just a normal string, and value can be anything. My problem is that the data type of the values can be different from row to row. Basically, I wanted to use checkboxes for boolean values and choices for lists. I have found a way to render the whole table column with checkboxes or choices by setting the cell factory:

final TableColumn<FieldValue, Field> valueColumn = new TableColumn<>("Value");
valueColumn.setCellFactory(new Callback<TableColumn<FieldValue, Field>, TableCell<FieldValue, Field>>() {
    @Override
    public TableCell<FieldValue, Field> call(final TableColumn<FieldValue, Field> column) {
        // if (value instanceof Boolean)
        return new CheckBoxTableCell<>();
    }
});

但我需要的是能够根据要在单元格内呈现的项目的类型插入条件.换句话说,某些细胞工厂是在细胞水平上而不是在列水平上.这会在渲染时评估我的状况.我还没有找到任何解决方案.也许有人有一些适当的技术来实现这种渲染?也许是一些 3rd 方数据网格?

But what I need is to be able to insert a condition based on the type of the item that is going to be rendered inside the cell. In other words, some cell factory on the cell level and not on the column level. And that evaluates my condition at the render time. I haven't found still any solution to that. Maybe someone has some proper techniques for implementing this sort of rendering? Maybe some 3rd party datagrid?

推荐答案

这是一个表格,显示了各种类型的字符串和对象对.

Here is a table displaying pairs of Strings and Objects of various types.

自定义单元工厂用于处理不同对象类型的显示(通过对对象类型执行 instanceof 检查并呈现适当的文本或图形).

A custom cell factory is used to handle display of different object types (by performing an instanceof check on the object's type and rendering the appropriate text or graphic).

import javafx.application.*;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ObservableValue;
import javafx.collections.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
import javafx.util.Callback;
import javafx.util.Pair;

public class PairTable extends Application {
    public static final String NAME_COLUMN_NAME  = "Name";
    public static final String VALUE_COLUMN_NAME = "Value";

    final TableView<Pair<String, Object>> table = new TableView<>();

    public static void main(String[] args) throws Exception {
        launch(args);
    }

    public void start(final Stage stage) throws Exception {
        // model data
        ObservableList<Pair<String, Object>> data = FXCollections.observableArrayList(
                pair("Song", "Bach Cello Suite 2"),
                pair("Image", new Image("http://upload.wikimedia.org/wikipedia/en/9/99/Bach_Seal.jpg")),
                pair("Rating", 4),
                pair("Classic", true),
                pair("Song Data", new byte[]{})
        );

        table.getItems().setAll(data);
        table.setPrefHeight(275);

        // table definition
        TableColumn<Pair<String, Object>, String> nameColumn = new TableColumn<>(NAME_COLUMN_NAME);
        nameColumn.setPrefWidth(100);
        TableColumn<Pair<String, Object>, Object> valueColumn = new TableColumn<>(VALUE_COLUMN_NAME);
        valueColumn.setSortable(false);
        valueColumn.setPrefWidth(150);

        nameColumn.setCellValueFactory(new PairKeyFactory());
        valueColumn.setCellValueFactory(new PairValueFactory());

        table.getColumns().setAll(nameColumn, valueColumn);
        valueColumn.setCellFactory(new Callback<TableColumn<Pair<String, Object>, Object>, TableCell<Pair<String, Object>, Object>>() {
            @Override
            public TableCell<Pair<String, Object>, Object> call(TableColumn<Pair<String, Object>, Object> column) {
                return new PairValueCell();
            }
        });

        // layout the scene.
        final StackPane layout = new StackPane();
        layout.getChildren().setAll(table);
        Scene scene = new Scene(layout);
        stage.setScene(scene);
        stage.show();
    }

    private Pair<String, Object> pair(String name, Object value) {
        return new Pair<>(name, value);
    }
}

class PairKeyFactory implements Callback<TableColumn.CellDataFeatures<Pair<String, Object>, String>, ObservableValue<String>> {
    @Override
    public ObservableValue<String> call(TableColumn.CellDataFeatures<Pair<String, Object>, String> data) {
        return new ReadOnlyObjectWrapper<>(data.getValue().getKey());
    }
}

class PairValueFactory implements Callback<TableColumn.CellDataFeatures<Pair<String, Object>, Object>, ObservableValue<Object>> {
    @SuppressWarnings("unchecked")
    @Override
    public ObservableValue<Object> call(TableColumn.CellDataFeatures<Pair<String, Object>, Object> data) {
        Object value = data.getValue().getValue();
        return (value instanceof ObservableValue)
                ? (ObservableValue) value
                : new ReadOnlyObjectWrapper<>(value);
    }
}

class PairValueCell extends TableCell<Pair<String, Object>, Object> {
    @Override
    protected void updateItem(Object item, boolean empty) {
        super.updateItem(item, empty);

        if (item != null) {
            if (item instanceof String) {
                setText((String) item);
                setGraphic(null);
            } else if (item instanceof Integer) {
                setText(Integer.toString((Integer) item));
                setGraphic(null);
            } else if (item instanceof Boolean) {
                CheckBox checkBox = new CheckBox();
                checkBox.setSelected((boolean) item);
                setGraphic(checkBox);
            } else if (item instanceof Image) {
                setText(null);
                ImageView imageView = new ImageView((Image) item);
                imageView.setFitWidth(100);
                imageView.setPreserveRatio(true);
                imageView.setSmooth(true);
                setGraphic(imageView);
            } else {
                setText("N/A");
                setGraphic(null);
            }
        } else {
            setText(null);
            setGraphic(null);
        }
    }
}

这篇关于JavaFX 2 TableView:根据单元格内的数据不同的单元格工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆