如何在JavaFX中将简单的双矩阵绘制成TableView?

时间:2017-01-20 19:34:24

标签: java javafx tableview

我想在JavaFX中创建一个简单的TableView,其中我的数据是像double[][]矩阵这样的二维数组,但我不知道如何实现这一点,一些建议?

1 个答案:

答案 0 :(得分:3)

正如法比安在评论中所说:

  1. 将表格定义为:

    TableView<double[]>
    
  2. double[][]数组的元素作为项添加到表中(从double[][]中提取元素并将其添加到ObservableList<double[]>)。

  3. 为您的表创建列,为每个列提供单元格值工厂。

    col.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()[c]))
    

    其中c是列索引。

  4. 如果您需要格式化单元格项目,还需提供cell factory

  5. matrix

    import javafx.application.Application;
    import javafx.beans.property.ReadOnlyObjectWrapper;
    import javafx.collections.FXCollections;
    import javafx.collections.ObservableList;
    import javafx.scene.Scene;
    import javafx.scene.control.TableColumn;
    import javafx.scene.control.TableView;
    import javafx.stage.Stage;
    
    import java.util.List;
    import java.util.Random;
    import java.util.stream.Collectors;
    import java.util.stream.IntStream;
    
    public class MatrixTable extends Application {
        private Random random = new Random(42);
        private static final int N_COLS = 4;
        private static final int N_ROWS = 100;
        private static final int MAX_DATA_VALUE = 100;
    
        public static void main(String[] args) {
            launch(args);
        }
    
        @Override
        public void start(Stage stage) {
            ObservableList<double[]> data = generateData();
    
            TableView<double[]> table = new TableView<>(data);
            table.getColumns().setAll(createColumns());
            table.setPrefSize(200, 250);
    
            stage.setScene(new Scene(table));
            stage.show();
        }
    
        private ObservableList<double[]> generateData() {
            return FXCollections.observableArrayList(
                    IntStream.range(0, N_ROWS)
                            .mapToObj(r ->
                                    IntStream.range(0, N_COLS)
                                            .mapToDouble(c -> randomValue())
                                            .toArray()
                            ).collect(Collectors.toList())
            );
        }
    
        private List<TableColumn<double[], Double>> createColumns() {
            return IntStream.range(0, N_COLS)
                    .mapToObj(this::createColumn)
                    .collect(Collectors.toList());
        }
    
        private TableColumn<double[], Double> createColumn(int c) {
            TableColumn<double[], Double> col = new TableColumn<>("C" + (c + 1));
            col.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()[c]));
    
            return col;
        }
    
        private long randomValue() {
            return Math.round(random.nextDouble() * MAX_DATA_VALUE  * 100) / 100.0;
        }
    }
    
      

    你能解释一下这行代码吗?

    col.setCellValueFactory(param -> new ReadOnlyObjectWrapper<>(param.getValue()[c]))
    

    来自javadoc

      

    需要设置单元格值工厂以指定如何填充单个TableColumn中的所有单元格。单元格值工厂是一个Callback,它提供TableColumn.CellDataFeatures实例,并期望返回一个ObservableValue。

    所以它正在做的是定义一种从行的double[]数据数据中提取列数据的方法(由param.getValue()提供)。因为我们在数据值周围使用ReadOnlyObjectWrapper,如果您使表格单元格可编辑(我在此示例中没有这样做),则不会将编辑后的值写回到数组中。包装器是将double数据值转换为ObservableValue(根据单元工厂接口的要求)所必需的。

    是的,我知道这很令人困惑,但这是为了让TableViews有效地被数百万个数据项virtualized controls支持而付出的代价。如果您不需要TableView的虚拟化功能和其他功能,则可以始终只使用GridPane中的标签。