【问题标题】:Java JTable object with multiple fields具有多个字段的 Java JTable 对象
【发布时间】:2009-12-30 21:55:51
【问题描述】:

我有一个包含 X 个字段的对象。我的 JTable 中的每一行对应一个项目。行中的每一列代表该项目的一个字段。我还需要维护对项目的引用(项目也有一个唯一的 ID 字段),以便我可以确定所选单元格中的项目。

首选的方法是将实际对象放在表格中的每个单元格中,并使用各种渲染器来显示项目,或者只是将字段值放在每个单元格中,并有一个包含项目 ID 的隐藏列需要知道商品 ID 时可以参考吗?

谢谢, 杰夫

【问题讨论】:

  • 它可能没有被格式化为一个问题,但实际上它确实要求一种首选方法。

标签: java swing jtable


【解决方案1】:

我会编写一个自定义表格模型(而不是试图将您的设计硬塞到默认表格模型实现中)。然后,此模型保存您的实际对象,并在其方法实现(例如 getValueAt)中,将每个字段视为一列。


简单示例(未经测试,但应该很好地说明这个想法):

import java.util.List;
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;

/**
 * Simple table model for displaying properties common to all objects.
 * Note that all methods must run inside the event dispatch thread.
 */
public class ObjectPropertyTableModel extends AbstractTableModel {
    private final List<Object> objects = new ArrayList<Object>();

    public void addObject(Object obj) {
        addObject(obj, objects.size());
    }

    public void addObject(Object obj, int index) {
        objects.add(index, obj);
        fireTableRowsInserted(index, index);
    }

    public void removeObject(Object obj) {
        int index = objects.indexOf(obj);
        objects.remove(index);
        fireTableRowsDeleted(index, index);
    }

    public Object getObject(int rowIndex) {
        return objects.get(rowIndex);
    }

    @Override
    public int getRowCount() {
        return objects.size();
    }

    @Override
    public int getColumnCount() {
        return 3;
    }

    @Override
    public String getColumnName(int columnIndex) {
        switch (columnIndex) {
        case 0: return "toString";
        case 1: return "hashCode";
        case 2: return "class";
        default: throw new IndexOutOfBoundsException();
        }
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
        case 0: return String.class;
        case 1: return Integer.class;
        case 2: return Class.class;
        default: throw new IndexOutOfBoundsException();
        }
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Object obj = objects.get(rowIndex);
        switch (columnIndex) {
        case 0: return obj.toString();
        case 1: return obj.hashCode();
        case 2: return obj.getClass();
        default: throw new IndexOutOfBoundsException();
        }
    }
}

【讨论】:

  • 这意味着一行中的每个单元格都会引用同一个对象,对吗?
  • 不完全。在自定义表格模型的情况下,单元格是“虚拟的”。当表格想要显示一个单元格时,它会调用您的getValueAt 方法。此时,访问您的对象的相关字段。
  • 是的,我的错。我在想如果我扩展 DefaultTableModel,而不是实现 TableModel。哎呀...谢谢。
  • 请注意,此解决方案不提供检索对一行对象的引用的方法。应该添加简单的方法来检索它。
【解决方案2】:

您也许可以使用Bean Table Model。如果没有,那么 JButtonTableModel 示例展示了如何实现 getValueAt/setValueAt() 方法并利用 RowTableModel 提供的功能,因此您无需从头开始创建 TableModel。

【讨论】:

  • 谢谢。不幸的是,它们不一定是 getXXX 方法。它们是 getProperty(XXX),因为属性是在运行时确定的,但这是一个很好的了解。
  • 这就是为什么我建议 JButtonTableModel 示例可能会更好,因为它可以通过重写几个方法轻松定制,并且您仍然拥有所需的所有功能。它支持检索行对象的方法,因此即使它在表中不可见,您也可以获得 ID。它还支持动态添加/删除行。
【解决方案3】:

我的首选方法是使用一个表模型,该模型从字段中为每列返回一个值。为了能够获得对对象的引用,我向模型中添加了一个可以称为 getObjectFromRow 的方法,顾名思义,它返回与行索引对应的对象。这样,您可以在单元格中获得实际显示的数据,并且不需要隐藏列来获取对行对象的引用。当然,这需要一个自定义表格模型,但我认为这很值得。
当然,也可以使用渲染器显示来自正确字段的数据,但根据我的经验,这有几个问题,包括为不同数据类型编写所有渲染器的麻烦,以及从表中复制和粘贴不起作用的事实开箱即用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-15
    • 1970-01-01
    • 2017-11-09
    • 2014-05-03
    • 2017-09-26
    • 2023-03-07
    • 2017-03-27
    • 1970-01-01
    相关资源
    最近更新 更多