创建自定义 Table 模型以提供来自 ArrayList 的数据

Creating a custom Table Model to provide data from ArrayList

我正在尝试创建一个 JTable,它根据来自 ArrayList 的信息创建 table。 ArrayList 填充了用户在 GUI 中输入的信息。每次用户按下 JButton 时,它应该向 table 添加一行新数据。

谷歌搜索后,似乎最好的方法是创建自定义 table 模型。我找不到关于如何执行此操作的体面教程。我查看了官方文档、一些随机站点和其他帖子。希望你们中的一个能给我指出正确的方向。

这是我当前 GUI 的图片。 JTable 应该填充中心区域:

这是我的一些代码:

 class dataModel extends AbstractTableModel
{
    private String[] columnName = {"Emp Num", "Base Pay", "Hours Worked", "Pay Amt"};

    public int getColumnCount()
    {
        return 4;
    }


    public int getRowCount()
    {
        return empData.size();
    }

    public Object getValueAt(int row, int col)
    {
        return new Integer(row*col);
    }
}

单击按钮时发生的 class。

class listener implements ActionListener
{
    @SuppressWarnings("unchecked")
    public void actionPerformed(ActionEvent e)
    {
        ArrayList empData = new ArrayList();

        int empNum = 0;
        double hourlyRate = 0;
        double hoursWorked = 0;
        try
        {
            empNum = Integer.parseInt(empNumField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Employee ID.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try
        {
            hourlyRate = Double.parseDouble(basePayField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Hourly Pay Rate.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }
        try
        {
            hoursWorked = Double.parseDouble(hrsField.getText());
        }
        catch(NumberFormatException event)
        {
            JOptionPane.showMessageDialog(null, "Invalid entry.\n\nPlease enter a number for the Hours Worked.", "Error", JOptionPane.WARNING_MESSAGE);
            return;
        }

        double payAMT = calculatePay(hourlyRate, hoursWorked);

        empData.add(empNum);
        empData.add(hourlyRate);
        empData.add(hoursWorked);
        empData.add(payAMT);

    }

你可以...

使用一个 DefaultTableModel,应该可以满足您的基本需求

private DefaultTableModel model;
//...
model = new DefaultTableModel(new String[] {"Emp Num", "Base Pay", "Hours Worked", "Pay Amt"}, 0);
table.setModel(model);

然后你可以直接向其中添加新数据

class listener implements ActionListener {

    private DefaultTableModel model;

    listener(DefaultTableModel model) {
        this.model = model;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        int empNum = 0;
        double hourlyRate = 0;
        double hoursWorked = 0;
        double payAMT = calculatePay(hourlyRate, hoursWorked);
        
        model.addRow(new Object[]{empNum, hourlyRate, hoursWorked, payAMT});
    }
}

没关系,它很简单,但这确实意味着您需要了解所呈现的数据的结构,并且不允许您管理可能有更多您以后可能想要使用的对象

现在,如果您想要更可定制的东西...

你可以...

使用自定义TableModel,首先,让我们从需求开始

public interface Employee {
    public int getNumber();
    public double getHourlyRate();
    public double getHoursWorked();
    public double getPay();
}

这定义了我们的模型可以管理的数据的基本期望。为什么?因为您可能有不同类型的员工或员工实现,其中包含更多信息,这与此 table 模型

无关

接下来,我们实现 TableModel...

public class DefaultWorkSheetTableModel extends AbstractTableModel {

    private List<Employee> items;

    public DefaultWorkSheetTableModel() {
        items = new ArrayList<>(25);
    }

    public DefaultWorkSheetTableModel(List<Employee> items) {
        this.items = items;
    }

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

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

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        switch (columnIndex) {
            case 0: return Integer.class;
            case 1: 
            case 2: 
            case 3: return Double.class;
        }
        return Object.class;
    }

    @Override
    public String getColumnName(int column) {
        switch (column) {
            case 0: return "Emp Num";
            case 1: return "Base Pay";
            case 2: return "Hours Worked";
            case 3: return "Pay Amount";
        }
        return null;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Employee item = items.get(rowIndex);
        switch (columnIndex) {
            case 0: return item.getNumber();
            case 1: return item.getHourlyRate();
            case 2: return item.getHoursWorked();
            case 3: return item.getPay();
        }
        return null;
    }

    public void add(Employee item) {
        items.add(item);
        int row = items.indexOf(item);
        fireTableRowsInserted(row, row);
    }

    public void remove(Employee item) {
        if (items.contains(item)) {
            int row = items.indexOf(item);
            items.remove(row);
            fireTableRowsDeleted(row, row);
        }
    }

}

这里发生了很多事情,但这涵盖了允许 JTable 呈现我们想要的数据的所有基本要求。

现在,当您想要添加数据时,您可以创建 Employee 的新实例并将其简单地添加到模型中...

class listener implements ActionListener {

    private DefaultWorkSheetTableModel model;

    listener(DefaultWorkSheetTableModel model) {
        this.model = model;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        int empNum = 0;
        double hourlyRate = 0;
        double hoursWorked = 0;
        //...
        DefaultEmployee employee = new DefaultEmployee(empNum, hourlyRate, hoursWorked);
        model.add(employee);
    }
}

是的,我知道我没有通过 payRate,那是因为它是特定于 Employee 实现的计算字段 ;)

JTable that creates the table based on information from an ArrayList.

Every time the user presses a JButton it should add a new row of data to the table.

所以你真正的需求是从一些文本字段中获取数据并将数据添加到 table.

因此无需使用 ArrayList 来执行此操作。

您可以为此使用 DefaultTableModelDefaultTableModel 支持 addRow(...) 方法。使用此方法,您可以添加包含来自 4 个文本字段的数据的 VectorArray

所以您的代码唯一真正的改变是:

//ArrayList empData = new ArrayList();
Vector empData = new Vector();

然后在将所有数据添加到 Vector 之后,您需要将 Vector 添加到 DefaultTableModel:

empData.add(payAMT);
model.addRow( empData );

因此,您当然需要首先创建一个仅包含列名称的空 DefaultTableModel,并且您的侦听器需要访问此模型。

it seems that the best way to do this is to create a custom table model. I cannot find a decent tutorial on how to do this

另一种选择是创建包含 Employee 个对象的自定义 TableModel。在这种情况下,您可以使用 ArrayList 来保存单个 Employee 对象。有关为此方法创建 TableModel 的示例,请查看 Row Table Model.