创建自定义 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 来执行此操作。
您可以为此使用 DefaultTableModel
。 DefaultTableModel
支持 addRow(...)
方法。使用此方法,您可以添加包含来自 4 个文本字段的数据的 Vector
或 Array
。
所以您的代码唯一真正的改变是:
//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.
我正在尝试创建一个 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 来执行此操作。
您可以为此使用 DefaultTableModel
。 DefaultTableModel
支持 addRow(...)
方法。使用此方法,您可以添加包含来自 4 个文本字段的数据的 Vector
或 Array
。
所以您的代码唯一真正的改变是:
//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.