如何以数组形式检索 JTable 数据

Posted

技术标签:

【中文标题】如何以数组形式检索 JTable 数据【英文标题】:How to Retrieve JTable Data as an Array 【发布时间】:2011-06-13 12:31:40 【问题描述】:

我已经通过具有 (Object[][] data, String[] headers) 构造函数的 DefaultTableModel 填充了 JTable。用户可以编辑表格,我希望能够将新数据加载回数组 (Object[][])。请注意,我宁愿不只是一点一点地更新数组,而是能够完全从表中加载一个新数组。如何做到这一点?

【问题讨论】:

【参考方案1】:

我想对 Manidip Sengupta 的回答提出一些小改进。与其将 table.getModel() 转换为适当的类,不如简单地使用 TableModel。这也使代码更具可重用性(实际上使用哪个 TableModel 实现并不重要)。

public Object[][] getTableData (JTable table) 
    TableModel dtm = table.getModel();
    int nRow = dtm.getRowCount(), nCol = dtm.getColumnCount();
    Object[][] tableData = new Object[nRow][nCol];
    for (int i = 0 ; i < nRow ; i++)
        for (int j = 0 ; j < nCol ; j++)
            tableData[i][j] = dtm.getValueAt(i,j);
    return tableData;

【讨论】:

【参考方案2】:

我收回这一点,第二个想法是,您不需要任何类型转换 - TableModel 是一个接口,它具有您需要的所有 3 个方法调用。 :)

总结:获取表的模型,检查其类并将其类型转换为适当的类(Abstract 或 Default TableModel),并使用其方法加载新创建的数组。一些伪代码:

public Object[][] getTableData (JTable table) 
    DefaultTableModel dtm = (DefaultTableModel) table.getModel();
    int nRow = dtm.getRowCount(), nCol = dtm.getColumnCount();
    Object[][] tableData = new Object[nRow][nCol];
    for (int i = 0 ; i < nRow ; i++)
        for (int j = 0 ; j < nCol ; j++)
            tableData[i][j] = dtm.getValueAt(i,j);
    return tableData;

您的标题不应被用户编辑更改。希望有帮助。问候, - M.S.

【讨论】:

【参考方案3】:

我已经通过 DefaultTableModel 用(Object[][] data, String[] headers)填充了一个 JTable

DefaultTableModel 是一个动态模型,这意味着可以动态添加行和列。数组不是动态的,因此当您使用数组创建 DefaultTableModel 时,数组中的数据会被复制到 Vector 的 Vector。

我希望能够将新数据加载回数组 (Object[][])。 我宁愿不只是一点一点地更新数组

很遗憾,您将不得不逐个单元格地更新数组,因为数据未存储在二维数组中。

或者,由于 DefaultTableModel 确实使用向量的向量来存储数据,因此您可以使用 getDataVector() 方法来访问数据。然后从 Vector 中获取每一行并在行 Vector 上调用 List.toArray() 方法,然后再将其添加到数组中。

无论哪种方式,您都需要遍历模型中的向量。

如果您想使用 2D 数组作为 TableModel 的存储,那么您将需要创建一个自定义 TableModel 使用提供的数组来存储数据。实现 TableModel 接口的所有必需方法后,您需要提供一个 getTableDataArray() 方法来返回对数组的引用。

【讨论】:

【参考方案4】:

使用开箱即用的 JTable 实现,您不能。当您使用 Object[][] rowData 初始化 JTable 时,该 rowData 由匿名 AbstractTableModel 实例使用,但不能从外部访问。

public JTable(final Object[][] rowData, final Object[] columnNames) 
    this(new AbstractTableModel() 
        public String getColumnName(int column)  return columnNames[column].toString(); 
        public int getRowCount()  return rowData.length; 
        public int getColumnCount()  return columnNames.length; 
        public Object getValueAt(int row, int col)  return rowData[row][col]; 
        public boolean isCellEditable(int row, int column)  return true; 
        public void setValueAt(Object value, int row, int col) 
            rowData[row][col] = value;
            fireTableCellUpdated(row, col);
        
    );

您可以考虑对 JTable 和 AbstractTableModel 进行子类化,并在 JTable 中“覆盖”此构造函数以创建您自己的 TableModel 实现,该实现将持有该 Object[][] 引用并以Object[][] getRowData() 返回它。或者,在构造函数中调用 super(...) 之后,将 rowData 保留为 JTable 子类本身中的一个字段——如果您真的不关心 MVC。

但是您需要确保在编辑表格后,初始模型被保留,而不是被带有setModel 的新模型对象(当然,不同类型的)替换。如果是这种情况,您想要实现的目标是不可能实现的——您需要遍历所有单元格。

【讨论】:

【参考方案5】:

不适用于现有的默认表模型。根据经验,您应该使用默认表模型。您应该实现自己的table model (MyTableModel)。您可以实现TableModel 或扩展AbstractTableModel。我建议后者,因为它提供了一些不错的实用方法。有两种方法可以实现您正在做的事情

    将新数据填充到MyTableModel 的新实例中并调用JTable.setModel()。 第二种方法是在MyTableModel 调用中创建一个方法,例如replaceData(T[][] data)。保留对表格当前显示的模型的引用。每当您想替换数据时,请致电replaceData()。假设您正在扩展AbstractTableModel,然后调用fireTableChanged() 通知表。

【讨论】:

请详细说明为什么永远不要使用 DefaultTableModel? 我第二个 Manidip 的问题。我们常用。 如果满足您的要求,使用 DefaultTableModel 没有任何问题。

以上是关于如何以数组形式检索 JTable 数据的主要内容,如果未能解决你的问题,请参考以下文章

如何从 mySQL 和 PHP 检索结果为多维数组?

我如何以反应形式检索可观察值?

如何通过在 Google 数据存储中传递 ID 数组作为输入来检索实体?

将 JDBC 数据库中的数据检索到 Jtable 中

如何从原始查询中检索结果集作为数组而不是 Laravel 3 中的对象

从本地存储中一一检索数组列表