我制作了一个按要求运行的简单应用程序:
这个方法其实很简单,JTable 实现了CellEditorListener,所以我们可以重写editingStopped(ChangeEvent) 方法并检查我们是否在表格的最后一个单元格中,如果是则添加一个新行。
所以你应该这样做:
//In the JTable class
@Override
public void editingStopped(ChangeEvent e)
{
//getting these values before calling super.editingStopped(e); because they get erased.
int row = getEditingRow();
int col = getEditingColumn();
super.editingStopped(e); //must call the super code to have a working edition
if (row == getRowCount() - 1 && col == getColumnCount() - 1)
{
getModel().createNewRow();
}
};
显然,我实现的 TableModel 和 TableCellEditor 和 JTable 是完成此任务的最低要求,您可以使用自己的,只需将调用更改为我为您使用的模型即可。
看起来像这样:
我建议使用 TAB 完成编辑,以便焦点转到下一个,当您处于最后一个时,它会跳转到新行的第一行。
完整代码:
import java.awt.Component;
import java.util.ArrayList;
import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;
public class TableEditingTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new TableEditingTest().createAndShowGUI();
}
});
}
private void createAndShowGUI()
{
JFrame frame = new JFrame("Table editing test");
MyTableModel model = new MyTableModel();
model.addRow(new String[]{"Some values", "so we have", "an actual table."});
model.addRow(new String[]{"This table", "is inititalized", "with an empty row:"});
model.createNewRow();
MyTable table = new MyTable(model);
table.setDefaultEditor(String.class, new MyStringTableCellEditor());
frame.add(new JScrollPane(table));
frame.setSize(600, 400); //use frame.pack() in a real application
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
private class MyTable extends JTable
{
public MyTable(MyTableModel model)
{
super(model);
}
@Override
public MyTableModel getModel()
{
return (MyTableModel) super.getModel();
}
@Override
public void editingStopped(ChangeEvent e)
{
int row = getEditingRow();
int col = getEditingColumn();
super.editingStopped(e);
if (row == getRowCount() - 1 && col == getColumnCount() - 1)
{
getModel().createNewRow();
}
};
}
private class MyTableModel extends AbstractTableModel
{
private static final int NUMBER_OF_COLUMNS = 3;
private ArrayList<String[]> values;
public MyTableModel()
{
values = new ArrayList<String[]>();
}
@Override
public String getColumnName(int col)
{
return "Column " + col;
}
@Override
public int getColumnCount()
{
return NUMBER_OF_COLUMNS;
}
@Override
public int getRowCount()
{
return values.size();
}
@Override
public Class<?> getColumnClass(int col)
{
return String.class;
}
@Override
public boolean isCellEditable(int row, int col)
{
return true;
};
@Override
public Object getValueAt(int row, int col)
{
return values.get(row)[col];
}
public void createNewRow()
{
addRow(null);
}
public void addRow(String[] rowValues)
{
if (rowValues == null)
{
values.add(new String[3]);
fireTableDataChanged();
}
else if (rowValues.length == 3)
{
values.add(rowValues);
fireTableDataChanged();
}
else throw new IllegalArgumentException("Expected an array of " + NUMBER_OF_COLUMNS + " strings, got " + rowValues.length + ".");
}
@Override
public void setValueAt(Object value, int row, int col)
{
values.get(row)[col] = value.toString();
}
}
private class MyStringTableCellEditor extends AbstractCellEditor implements TableCellEditor
{
private JTextField editorField = new JTextField();
@Override
public Object getCellEditorValue()
{
return editorField.getText();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
editorField.setText((String) value);
return editorField;
}
}
}