当前位置: 首页 > 知识库问答 >
问题:

从编程定义的结构填充javaFX TableView的最佳方法

施彬郁
2023-03-14

我这里有一个相对复杂的JavaCRUD用Swing组件编写。我正在考虑在JavaFX中重写它的GUI。现在的问题是:

我创建了一个类,用于保存下载的数据、存储SQL命令和有关任何给定表的其他信息。我在表的构造函数中定义了该表的数据结构。这样地:

    vyrData = new KTable(
        "manufacturers",                      //Name of the table
        "select * from manufacturers ",       //SQL select of it
        " order by name ",                    //Ordering
        "",                                   //Limiting
        new String[]    {"id", "name"},       //Column names in database
        null,                                 //Column names for GUI (if differ from db ones)
        new Class<?>[]  {Long.class, String.class}, //Column types
        false,                                // ...if the table should be limited by size.
        false                                 // ...if the table should be read in reverse order
        );

这样一来,每当数据库表结构发生变化时,我就不必接触这个类的代码。我将镜像构造函数中的更改,并相应地编辑GUI。

(在类内部,数据存储为ArrayList。可能不是最干净的解决方案,但工作得很好。对象[][]也会做我猜。)

现在,JavaFX TableView使用了observable list,出于更新的原因,这是我喜欢的想法,但到目前为止,我看到的每个教程都为它提供了带有硬编码属性名、setter和getter的自定义数据对象。这与使用一个类来存储任何表的想法相矛盾。

是否有可能以某种方式以编程方式生成数据结构,但仍然使用可观察列表?如果不是的话,从2D阵列中移植teble最简单的解决方案是什么?

感谢任何帮助。

共有1个答案

阳宗清
2023-03-14

您可以使用任何您想要存储数据的数据结构,但是您应该记住以下几点:

  • 表格视图中,每行需要一项。这些项可能是数据本身,也可能只是用于在自定义数据结构中查找数据的键

TableColumncellValueFactory用于检索表格单元格中显示的数据。您可以使用它来检索给定TableView项的数据。请注意,它必须返回ObservableValue,如果数据发生变化,监听器将被注册到预期收到通知的返回值。

在下面的示例中,将数据存储在观测地图中

public static ObservableMap<Long, ObservableList<Object>> createData(long[] ids, Object[][] values) {
    ObservableMap<Long, ObservableList<Object>> map = FXCollections.observableHashMap();
    for (int i = 0; i < values.length; i++) {
        map.put(ids[i], FXCollections.observableArrayList(values[i]));
    }
    return map;
}
    ObservableMap<Long, ObservableList<Object>> data = createData(
            new int[]{1, 2, 3, 4},
            new Object[][]{
                new Object[]{"John Doe"},
                new Object[]{"Leia Organa"},
                new Object[]{"Nathasha Romanov"},
                new Object[]{"Tony Stark"}
            });

    // list of map keys
    ObservableList<Long> rowIDs = FXCollections.observableArrayList(data.keySet());
    data.addListener((MapChangeListener<Long, ObservableList<Object>>) (m -> {
        if (m.wasAdded()) {
            rowIDs.add(m.getKey());
        }
        if (m.wasRemoved()) {
            rowIDs.remove(m.getKey());
        }
    }));

    TableView<Long> tv = new TableView<>(rowIDs);

    // column displaying the ID
    TableColumn<Long, Long> idColumn = new TableColumn<>("id");
    idColumn.setCellValueFactory(c -> Bindings.createObjectBinding(() -> c.getValue()));

    tv.getColumns()
            .setAll(idColumn,
                    createColumn("name", (index) -> Bindings.valueAt(data.get(index), 0)));
public static <I, O> TableColumn<I, O> createColumn(String columnName, Function<I, ObservableValue<O>> valueGetter) {
    TableColumn<I, O> column = new TableColumn<>(columnName);
    column.setCellValueFactory(c -> {
        I item = c.getValue();
        return valueGetter.apply(item);
    });
    return column;
}

这可能比你需要的更复杂...简单地将行存储为观测列表s(或Object[]/List)会简单得多

TableView<ObservableList<Object>> tv = new TableView<>();
tv.getItems().setAll(FXCollections.observableArrayList(1, "John Doe"),
        FXCollections.observableArrayList(2, "Leia Organa"),
        FXCollections.observableArrayList(3, "Nathasha Romanov"),
        FXCollections.observableArrayList(4, "Tony Stark"));

// columns created using createColumn(<column name>, l -> Bindings.valueAt(l, <data index>))
tv.getColumns().setAll(createColumn("id", l -> Bindings.valueAt(l, 0)),
        createColumn("name", l -> Bindings.valueAt(l, 1)));

如您所见,鉴于数组包含列名(使用循环),在这两种情况下都很容易创建表列。

 类似资料:
  • 我正在创建一个订单服务,这是RestServices世界的新功能。 我需要将订单模型读入并在DB中持久化。 为此,我有以下方法: 一切正常,但我对目前的设计有顾虑: 我正在读取输入到DTO 要存储对象,我将转换为订单对象,它将由Hibernate保存 再次发送响应回来,我正在将实际的订单对象转换为DTO。 最后,我将创建每个请求4-5个对象,如果我的应用程序得到100个请求,它可能会遇到内存问题。

  • 我们有一个微型应用程序,它由前端开发人员组装起来,然后“翻墙而去”。它定义了一个属性文件settings.js: 由html引用: 我想在运行时在application.yml中定义solr路径,如下所示: ) 可能 我曾考虑将'settings.js'作为一个Tymeleaf模板(settings.js.html),并让一个spring控制器从application.properties填充模型

  • 问题内容: 当前,我们的开发团队使用这种模式,但是我不禁想知道是否存在更快或更有效的html方式来完成同一任务。 的HTML 这是Javascript: 问题答案: 这是我为此编写的函数。我不确定它是否比jQuery Templates更快。 它一次创建并附加一个Option元素,这可能比Templates慢 。我怀疑Templates会构建整个HTML字符串,然后一次创建所有DOM元素。那可能更

  • 问题内容: 我已经看到了许多不同的方法来创建和填充数字表。但是,创建和填充一个的最佳方法是什么?从“最重要”到“最不重要”定义“最佳”: 用最佳索引创建的表 产生最快的行 用于创建和填充的简单代码 问题答案: 这是一些从网上获取的代码示例,以及对该问题的解答。 对于每种方法,我都修改了原始代码,因此每种方法都使用相同的表和列:NumbersTest和Number,具有10,000行或尽可能接近的行

  • 问题内容: 我是PyQt的新手,正在努力填充QTableView控件。 我的代码如下: 实际上,在代码中,我成功地填充了QListView,但是未显示我设置为QTableView的值,您还可以看到我将行截断为10,因为它永远需要显示数据帧的数百行。 那么,从熊猫数据框中填充表模型的最快方法是什么? 提前致谢。 问题答案: 就我个人而言,我将创建自己的模型类以使其处理起来更加容易。 例如:

  • 如何以编程方式从java代码填充旋转器? 我在布局中有一个旋转器,如下所示: