问题
This is my first time asking here so forgive me if something isn't appropriate, and sorry if my English isn't very good.
Well, to make it short, currently I'm developing a Java desktop app with Swing and I have a problem using table. I have rows with each row have a button to delete the row. Everything is okay (i can delete rows with no problem) until i try to delete the last row. The last row can be deleted but apparently there is an exception, something like this:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 4 >= 4
at java.util.Vector.elementAt(Vector.java:427)
at javax.swing.table.DefaultTableModel.setValueAt(DefaultTableModel.java:648)
at javax.swing.JTable.setValueAt(JTable.java:2710)
at javax.swing.JTable.editingStopped(JTable.java:4712)
at javax.swing.AbstractCellEditor.fireEditingStopped(AbstractCellEditor.java:125)
From the stack trace, it seems that "4" is my previously deleted last row index, but i have no idea how to deal with this. I already search for solution but i still can't solve it. Note that there are still other rows when i delete the last row, and after that i can't delete the others rows. The same exception also resulted when i click the delete button.
Oh. and I use removeRow() from DefaultTableModel to delete the row. Any help will be appreciated. Thanks.
EDIT These are the code I use.
public class ViewDetail extends JInternalFrame implements ActionListener {
...
String column[] = { "Aaa", "Bbb", "Delete This"};
tableModel = new DefaultTableModel();
Object row[][] = new Object[size][column.length];
//fill the data from db
int r = 0;
for (int i = 0; i < size; i++) {
row[r][0] = ...;
row[r][1] = ...;
row[r][2] = "Delete";
r++;
}
tableModel.setDataVector(row, column);
table = new JTable(tableModel);
tableColumn = table.getColumn("Aaa");
tableColumn.setPreferredWidth(75);
tableColumn = table.getColumn("Bbb");
tableColumn.setPreferredWidth(75);
tableColumn = table.getColumn("Delete This");
tableColumn.setPreferredWidth(75);
tableColumn.setCellRenderer(new ButtonRenderer());
tableColumn.setCellEditor(new ButtonEditor(new JCheckBox());
...
}
public class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
}
setText((value == null) ? "" : value.toString());
return this;
}
}
public class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private String label;
private boolean isPushed;
private JTable table;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
this.table = table;
return button;
}
public Object getCellEditorValue() {
if (isPushed) {
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
tableModel.removeRow(table.getSelectedRow());
}
isPushed = false;
return new String(label);
}
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
回答1:
Swing is trying to set the new value into the row you remove! Try moving the remove code into a Runnable and use invokeLater in the swing utility class to execute it.
回答2:
could you post the code where you init, add elements and delete in your JTable?
My first guess is that you are either doing the classical mistake "I have 4 elements in my table so to delete the last one I remove(4)" when you your table goes from 0 to 3 in indices
or you are trying to remove several object in the same loop like
for(int i = 0; i<lenght; i++){
if(i%2==0){//every even number
tab.remove(i);
}
}
then your are modifying the size of your table, the elements are shifted but your not taking it in account when removing.
those are just guesses/pointer to what might cause the problem. please post your code if this doesn't solve it
回答3:
The Table Button Column shows how you can render a column as a button and how to add an Action that is executed when the button is clicked. The example Action just happens to show how to delete a row.
回答4:
Here you need to remove only 0 th row that should be iterated
private void refreshTable() { int rowCount= model.getRowCount(); // System.out.println(rowCount);
for(int i=0;i<rowCount;i++ ){
model.removeRow(0);
//System.out.println(i);
}
}
回答5:
you can add new vaiable and check to fireEditingStopped() :
public class ButtonEditor extends DefaultCellEditor {
//create new variable
private boolean isDeleteRow = false;
/////////////////
protected JButton button;
private String label;
private boolean isPushed;
private JTable table;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
this.table = table;
// set false when click to button
isDeleteRow = false;
/////////////////
return button;
}
public Object getCellEditorValue() {
if (isPushed) {
// set true when isPushed button
isDeleteRow = true;
/////////////////
}
isPushed = false;
return new String(label);
}
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
//check if isDeleteRow, remove row
if(isDeleteRow)
{
DefaultTableModel tableModel = (DefaultTableModel) table.getModel();
tableModel.removeRow(table.getSelectedRow());
}
/////////////////
}
}
来源:https://stackoverflow.com/questions/4274544/problem-with-removing-last-row-of-jtable