【问题标题】:Creating a custom Table Model to provide data from ArrayList创建自定义表模型以提供来自 ArrayList 的数据
【发布时间】:2017-08-23 16:46:38
【问题描述】:

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

在谷歌上搜索后,似乎最好的方法是创建一个自定义表格模型。我找不到关于如何做到这一点的体面教程。我查看了官方文档,以及一些随机站点和其他帖子。希望你们中的一个人能指出我正确的方向。

这是我当前 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 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);

    }

【问题讨论】:

  • This answers 演示了一个由List 支持的自定义TableModel,它甚至可以添加/删除删除
  • 根据现有信息,DefaultTableModel 会做你想做的事
  • 这个example 说明了一个TableModel 有一个Map<String, String>

标签: java swing arraylist jtable


【解决方案1】:

根据来自 ArrayList 的信息创建表的 JTable。

每次用户按下 JButton 时,它都应该向表中添加一个新的数据行。

所以您真正的需求是从一些文本字段中获取数据并将数据添加到表格中。

因此没有必要使用 ArrayList 来执行此操作。

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

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

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

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

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

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

似乎最好的方法是创建一个自定义表格模型。我找不到关于如何做到这一点的像样的教程

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

【讨论】:

    【解决方案2】:

    你可以...

    使用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();
    }
    

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

    接下来,我们实现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 实现的计算字段;)

    【讨论】:

    • 感谢您如此彻底的回复。这真的很有帮助,我终于有办法解决这个问题了!
    • 我使用了你的第一个解决方案,更简单的一个。我工作的下一部分是在选择单选按钮时更新表中的特定单元格值 payAMT 变量。因此,如果当前 payAMT 为 500,则按下 5% 单选按钮应将表中的该值增加 5%。我试过使用 model.setValueAt,但得到了一个 arrayIndexOutofBounds 异常。
    • @Justiciar 如果没有更多上下文,很难知道可能出了什么问题。考虑发布一个新问题来证明您的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 2016-05-29
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 2018-01-12
    相关资源
    最近更新 更多