Shouldn't the new Boolean appear as a checkbox? It's showing up as a true/false string value instead. This is how I'm populating the data:
Object[] columnNames4 = {"Name", "City", "Checkbox"};
Object[][] data = {
{"john smith",
"x", new Boolean(false)},
{"jenny m",
"y", new Boolean(false)}
};
JTable table4 = new JTable(data, columnNames4);
JScrollPane S3 = new JScrollPane(table4);
S3.setPreferredSize(new Dimension(300, 300));
Create a subclass ofAbstractTableModel and return Boolean.class in the Method getColumnClass() for the column you want.
You need to setup a TableCellRenderer and TableCellEditor
see http://docs.oracle.com/javase/tutorial/uiswing/components/table.html
Once you have defined the render's / editor's you can
define the render/editor as the default render for a Type
table.setDefaultRenderer(Boolean.class, new MyBooleanRender());
table.setDefaultEditor(Boolean.class, new MyBooleanCellEditor());
define the render / editor to a column
TableColumnModel tcm = table.getColumnModel();
tcm.getColumn(4).setCellRenderer(new MyBooleanRender());
tcm.getColumn(4).setCellEditor(new MyBooleanCellEditor());
You can define a checkbox cellRender like:
public class MyBooleanRender extends JCheckBox
implements TableCellRenderer {
private JCheckBox checkBox = this;
/**
* #see javax.swing.table.TableCellRenderer#getTableCellRendererComponent
* (javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
*/
public Component getTableCellRendererComponent(
JTable tbl,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
boolean val = false;
if (Common.isEmpty(value)) {
checkBox.setSelected(false);
} else {
try {
val = ((Boolean) value).booleanValue();
} catch (Exception e) {
}
checkBox.setSelected(val);
}
if (Common.OPTIONS.highlightEmpty.isSelected() && value == Common.MISSING_VALUE) {
checkBox.setBackground(Common.EMPTY_COLOR);
} else if (value == Common.MISSING_REQUIRED_VALUE) {
checkBox.setBackground(Common.MISSING_COLOR);
} else {
...
}
checkBox.setSelected(val);
return checkBox;
}
}
For a checkboxEditor, you can use the DefaultCellEditor class.
Related
I would like to know how to set up a JComboBox in a particular cell in a JTable.
I have seen people using TableColumn setCellEditor(new DefaultCellEditor(comboBox)).
But this is for an entire column, I would like a specific cell.
So maybe I should do a custom TableCellEditor that would fit my needs, but I am a little lost on how to do it...
The goal of this is to manage filters on parameters. There are two kinds of filters:
The one that compares two values, for instance: number of balloons > 5
The one that will say is a value is inside a range of value, for instance: parameter name is inside {"one", "two", "three", "seven"}.
screenshot of my JTable:
As we can see in the picture, when there is the "comparator" "is among", we would need a JComboBox in cell[0][2] to choose the values of the range within a complete set of fields.
While cell[1][2] does not need a JComboBox, but just an editable cell.
I hope I have been clear and thank you for your help.
EDIT:
I was able to display a JComboBox only to realize, I couldn't select multiple values on it. So now I am trying to display a JList instead of a ComboBox.
But when I click on the cell, the JList is not displayed, I don't know why.
Here is my code:
JTable tableParametersFilter = new JTable(modelParametersFilter){
// Determine editor to be used by row
public TableCellEditor getCellEditor(int row, int column)
{
int modelColumn = convertColumnIndexToModel( column );
int modelRow = convertRowIndexToModel( row );
Parameter_Filter pf = view.listParameter_Filter.get(modelRow);
if(modelColumn == 2 && pf instanceof Parameter_Filter_To_List_Of_Fields) {
Parameter_Filter_To_List_Of_Fields pftlof = (Parameter_Filter_To_List_Of_Fields)pf;
JList<String> list = new JList<String>(pftlof.list_of_fields_total_names);
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
list.setLayoutOrientation(JList.VERTICAL_WRAP);
list.setVisibleRowCount(-1);
return new TableCellEditor() {
#Override
public boolean stopCellEditing() {
return false;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return false;
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public Object getCellEditorValue() {
return list.getSelectedValuesList().toString();
}
#Override
public void cancelCellEditing() {
}
#Override
public void addCellEditorListener(CellEditorListener l) {
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return list;
}
};
}
return super.getCellEditor(row, column);
}
};
Any suggestions?
I have solved my problem.
I have not been able to add multiple choice JComboBox, or a displayable JList on the Cell of the Jtable.
Instead, I have used a JOptionPane that displayed a JList.
Here's the code:
tableParametersFilter.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
JTable target = (JTable)e.getSource();
int row = target.getSelectedRow();
int column = target.getSelectedColumn();
if(column == 2){
Parameter_Filter pf = view.listParameter_Filter.get(row);
if(pf instanceof Parameter_Filter_To_List_Of_Fields) {
Parameter_Filter_To_List_Of_Fields pftlof = (Parameter_Filter_To_List_Of_Fields) pf;
JList<String> jlist = new JList<String>(pftlof.list_of_fields_total_names);
String StringOfIntArray = (String) tableParametersFilter.getValueAt( row, 2);
int[] list_parameter_id = Statique.StringOfIntArrayToIntegerArray(StringOfIntArray);
if(list_parameter_id.length < jlist.getModel().getSize()) {
int[] list_places = pftlof.getPlaceOfParameters(list_parameter_id);
for(int i = 0; i < list_places.length; i++) {
jlist.setSelectedIndices(list_places);
}
}
JScrollPane scrollPane = new JScrollPane(jlist);
scrollPane.setPreferredSize( new Dimension( 500, 500 ) );
JOptionPane.showMessageDialog(
null, scrollPane, "Multi-Select Example", JOptionPane.PLAIN_MESSAGE);
int[] SelectedIndices = jlist.getSelectedIndices();
Integer[] listParametersId = new Integer[SelectedIndices.length];
for(int i = 0; i < SelectedIndices.length; i++) {
int id = pftlof.list_of_fields_Total[SelectedIndices[i]].id;
try {
Parameter p = Parameter.getParameter(
id,
Parameter_Filter_To_List_Of_Fields.getTotal_Parameter_In_Parameter_Filter_To_List_Of_Fields());
listParametersId[i] = p.id;
} catch (NoSuchFieldException e1) {
e1.printStackTrace();
}
}
System.out.println(Arrays.toString(listParametersId));
tableParametersFilter.setValueAt(Arrays.toString(listParametersId), row, 2);
}
}
}
}
I am sorry if the title is not explanatory enough.
I have written a small extension to DefaultTableRenderer class in Java in order to specify cellBackgourd, cellForeground, Alignment and decimal control. I using this class in matlab to control and customise JIDE tables. But have re-created the issue in Java, in order to increase chances of a reply or a possible workaround.
I am successfully able to set cell Background, Foreground, alignment and decimal places as required when the table initialises and displays. However, as soon as I select a row/cell I loose decimal control on displayed data as shown in figure below. Please note that I am using specific cell selection colours, I guess, I am not implementing it properly.
I think, the problem is one of last two lines:
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
or
return cell;
Java code:
import java.awt.*;
import java.text.DecimalFormat;
import javax.swing.*;
import javax.swing.table.*;
public class DecimalPlacesInTable extends JFrame {
public static void main( String[] args ) {
DecimalPlacesInTable frame = new DecimalPlacesInTable();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setVisible( true );
}
public DecimalPlacesInTable() {
Object[] columnNames = { "A", "B", "C" };
Object[][] data = {
{new Double( 850.503 ), new Double( 850.545 ), new Double( 80.54553 ) },
{new Double( 50.52503 ), new Double( 36.4554 ), new Double( 50.41453 ) },
{new Double( 80.544653 ), new Double( 8.3 ), new Double( 80.4553 ) },
{new Double( 50.1553 ), new Double( 246.0943 ), new Double( 50.455 ) }};
JTable table = new JTable(data, columnNames);
// Tell the table what to use to render our column of doubles
for (int i=0; i<3; i++) {
table.getColumnModel().getColumn(i).setCellRenderer(new DecimalFormatRenderer());
getContentPane().add(new JScrollPane(table));
}
}
// Custom Renderer class
static class DecimalFormatRenderer extends DefaultTableCellRenderer
{
public Component getTableCellRendererComponent
(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JComponent cell = (JComponent) super.getTableCellRendererComponent
(table, value, isSelected, hasFocus, row, column);
// set color
cell.setBackground(new Color(0xC8C8C8));
cell.setForeground(new Color(0xFFFFFF));
//set Alignment
((JLabel) cell).setHorizontalAlignment(SwingConstants.CENTER);
//set selection colors
if (isSelected) {
cell.setBackground(new Color(0x3399FF));
cell.setForeground(new Color(0x000000)); // AM
} else {
// set decimals
DecimalFormat DecimalFormatter = new DecimalFormat("#.00");
value = DecimalFormatter.format(value);
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
return cell;
}
}
}
From Concepts: Editors and Renderers - How to Use Tables (The Java? Tutorials > Creating a GUI With JFC/Swing > Using Swing Components)
It is easy to customize the text or image rendered by the default renderer, DefaultTableCellRenderer. You just create a subclass and implement the setValue method so that it invokes setText or setIcon with the appropriate string or image. For example, here is how the default date renderer is implemented:
import java.awt.*;
import java.text.DecimalFormat;
import javax.swing.*;
import javax.swing.table.*;
public class DecimalPlacesInTable2 extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
DecimalPlacesInTable2 frame = new DecimalPlacesInTable2();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
});
}
public DecimalPlacesInTable2() {
Object[] columnNames = { "A", "B", "C" };
Object[][] data = {
{850.503, 850.545, 80.54553},
{50.52503, 36.4554, 50.41453},
{80.544653, 8.3, 80.4553},
{50.1553, 246.0943, 50.455}
};
//JTable table = new JTable(data, columnNames);
TableModel model = new DefaultTableModel(data, columnNames) {
#Override public Class<?> getColumnClass(int column) {
return Double.class;
}
};
JTable table = new JTable(model);
// Tell the table what to use to render our column of doubles
for (int i = 0; i < 3; i++) {
table.getColumnModel().getColumn(i).setCellRenderer(new DecimalFormatRenderer());
//getContentPane().add(new JScrollPane(table));
}
getContentPane().add(new JScrollPane(table));
}
// Custom Renderer class
static class DecimalFormatRenderer extends DefaultTableCellRenderer {
private final DecimalFormat formatter = new DecimalFormat("#.00");
#Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel cell = (JLabel) super.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, column);
//set Alignment
cell.setHorizontalAlignment(SwingConstants.CENTER);
//set selection colors
if (isSelected) {
cell.setBackground(new Color(0x3399FF));
cell.setForeground(new Color(0x000000)); // AM
} else {
// set color
cell.setBackground(new Color(0xC8C8C8));
cell.setForeground(new Color(0xFFFFFF));
}
// // set decimals
// if (value instanceof Double) {
// cell.setText(formatter.format(value));
// }
return cell;
}
#Override public void setValue(Object value) {
setText(value instanceof Double ? formatter.format(value) : "");
}
}
}
I've a JTable set to display String and Boolean values in the same column. I've the following piece of code to setup renderers for both the object types.
table.setDefaultRenderer(Boolean.class, new BooleanHandler());
table.setDefaultRenderer(String.class, new StringHandler());
table.setDefaultRenderer(
Object.class,
new DefaultTableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
System.out.println("Inside overridden function");
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus,row, column);
}
}
);
The issue I face is that, the renderer for Object gets called always instead of Boolean or String. I tried removing the renderer for Object, still no luck.
I've a JTable set to display String and Boolean values in the same column
Then you can't just use the normal rendering logic.
Normally the renderer is choosen based on the value returned by the getColumnClass(...) method. However, this is column based, not cell based so you won't know which renderer to return.
Instead you need to override the getCellRenderer(...) and getCellEditor(...) methods to return the renderer/editor based on the data in the cell.
An example of this approach is given below:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TablePropertyEditor extends JFrame
{
public TablePropertyEditor()
{
String[] columnNames = {"Type", "Value"};
Object[][] data =
{
{"String", "I'm a string"},
{"Date", new Date()},
{"Integer", new Integer(123)},
{"Double", new Double(123.45)},
{"Boolean", Boolean.TRUE}
};
JTable table = new JTable(data, columnNames)
{
private Class editingClass;
public TableCellRenderer getCellRenderer(int row, int column)
{
editingClass = null;
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == 1)
{
Class rowClass = getModel().getValueAt(row, modelColumn).getClass();
return getDefaultRenderer( rowClass );
}
else
return super.getCellRenderer(row, column);
}
public TableCellEditor getCellEditor(int row, int column)
{
editingClass = null;
int modelColumn = convertColumnIndexToModel(column);
if (modelColumn == 1)
{
editingClass = getModel().getValueAt(row, modelColumn).getClass();
return getDefaultEditor( editingClass );
}
else
return super.getCellEditor(row, column);
}
// This method is also invoked by the editor when the value in the editor
// component is saved in the TableModel. The class was saved when the
// editor was invoked so the proper class can be created.
public Class getColumnClass(int column)
{
return editingClass != null ? editingClass : super.getColumnClass(column);
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane( table );
getContentPane().add( scrollPane );
}
public static void main(String[] args)
{
TablePropertyEditor frame = new TablePropertyEditor();
frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
The above code just uses the default String and Boolean renderers and editors.
The other approach would be to create custom renderers and editors so that each is aware of the two possible data types and returns the appropriate renderer/editor.
Displaying data in a JTable. One column serves as a field Checkbox. The problem is that instead of the icon appears in the display ChceckBox true / false. How do I fix this?
Add data:
private DefaultTableModel headermodel = new DefaultTableModel();
private JScrollPane scrollHeader = new JScrollPane();
private JTable headerTable = new JTable();
public void loadHead(){
header = model.getHead();
int ids=0;
int id=1;
for(String head: header) {
headermodel.addRow(new Object[]{id,head});
headerMap.put(ids,head);
id++;
ids++;
count++;
}
header.clear();
}
and display data in JTable:
headerTable = new JTable(headermodel);
headermodel.addColumn("Lp.");
headermodel.addColumn("Column Name");
headermodel.addColumn("Constraint");
headermodel.addColumn("Sum");
scrollHeader = new JScrollPane(headerTable);
TableColumnModel tcm = headerTable.getColumnModel();
tcm.getColumn(2).setCellEditor(new DefaultCellEditor(new JCheckBox()));
tcm.getColumn(3).setCellEditor(new DefaultCellEditor(new JCheckBox()));
tcm.getColumn(3).setCellRenderer(headerTable.getDefaultRenderer(boolean.class));
add(scrollHeader);
The model's getColumnClass(int columnIndex) method should return Boolean.class for the appropriate column index so that the renderer knows to render a check box for that column. For example,...
DefaultTableModel headermodel = new DefaultTableModel(){
#Override
public Class<?> getColumnClass(int columnNumber) {
if (columnNumber == 2 || columnNumber == 3) {
return Boolean.class;
} else {
return super.getColumnClass(columnNumber);
}
}
}
You shouldn't have to set the cell renderer for these columns for this since the default cell renderer will handle Boolean.class appropriately.
Even I read and test answers by #kleopatra
How do I correctly use customer renderers to paint specific cells in a JTable?
particular one table header color java swing
about super.getTableCellRendererComponent(...) must be last code line before returns, I'm not able to write correct Renderer by those suggestion, for me works only this way
JLabel is added for Borders, HorizontalAlignment and Foreground, especially Background caused me a few non_senses by using Component instead of JLabel, (not important here somehow)
from SSCCE
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class SelectedTableHeader {
private JFrame frame = new JFrame("Table Demo");
private JTableHeader header;
private Object selectedColumn = null;
private String[] columnNames = {"String", "Integer", "Float", "Double", "Locale & Double", "Boolean"};
private Object[][] data = {
{"aaa", new Integer(12), new Float(12.15), new Double(100.05), new Double(12.05), true},
{"bbb", new Integer(5), new Float(7.154), new Double(6.1555), new Double(417.55), false},
{"CCC", new Integer(92), new Float(0.1135), new Double(3.1455), new Double(11.05), true},
{"ddd", new Integer(12), new Float(31.15), new Double(10.05), new Double(23.05), true},
{"eee", new Integer(5), new Float(5.154), new Double(16.1555), new Double(17.55), false},
{"fff", new Integer(92), new Float(4.1135), new Double(31.1455), new Double(3.05), true}};
private TableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
#Override
public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
private JTable table = new JTable(model);
public SelectedTableHeader() {
header = table.getTableHeader();
header.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
JTableHeader h = (JTableHeader) e.getSource();
int i = h.columnAtPoint(e.getPoint());
Object o = h.getColumnModel().getColumn(i).getHeaderValue();
if (i < 0) {
selectedColumn = null;
return;
}
selectedColumn = o;
h.requestFocusInWindow();
}
});
final TableCellRenderer hr = table.getTableHeader().getDefaultRenderer();
header.setDefaultRenderer(new TableCellRenderer() {
private JLabel lbl;
#Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (selectedColumn == value) {
lbl = (JLabel) hr.getTableCellRendererComponent(table, value, true, true, row, column);
lbl.setBorder(BorderFactory.createCompoundBorder(lbl.getBorder(), BorderFactory.createLineBorder(Color.red, 1)));
lbl.setHorizontalAlignment(SwingConstants.LEFT);
} else {
lbl = (JLabel) hr.getTableCellRendererComponent(table, value, false, false, row, column);
lbl.setBorder(BorderFactory.createCompoundBorder(lbl.getBorder(), BorderFactory.createEmptyBorder(0, 5, 0, 0)));
lbl.setHorizontalAlignment(SwingConstants.CENTER);
}
if (column == 0) {
lbl.setForeground(Color.red);
} else {
lbl.setForeground(header.getForeground());
}
/*return (value == selectedColumn) ? hr.getTableCellRendererComponent(
table, value, true, true, row, column) : hr.getTableCellRendererComponent(
table, value, false, false, row, column);*/
return lbl;
}
});
table.setRowHeight(20);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scroll = new JScrollPane(table);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(scroll);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
SelectedTableHeader selectedTableHeader = new SelectedTableHeader();
}
});
}
}
In my experience, it's better to get the DefaultTableCellHeaderRenderer when you overwrite any JTable Renderer. So, instead of messing with the JLabel from the Renderer directly, you grab the Renderer with super(). So, your code should look like this:
header.setDefaultRenderer(new DefaultTableCellHeaderRenderer() {
#Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellHeaderRenderer rendererComponent = (DefaultTableCellHeaderRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (selectedColumn == value) {
rendererComponent.setBorder(BorderFactory.createCompoundBorder(rendererComponent.getBorder(), BorderFactory.createLineBorder(Color.red, 1)));
rendererComponent.setHorizontalAlignment(SwingConstants.LEFT);
} else {
rendererComponent.setBorder(BorderFactory.createCompoundBorder(rendererComponent.getBorder(), BorderFactory.createEmptyBorder(0, 5, 0, 0)));
rendererComponent.setHorizontalAlignment(SwingConstants.CENTER);
}
if (column == 0) {
rendererComponent.setForeground(Color.red);
} else {
rendererComponent.setForeground(header.getForeground());
}
return rendererComponent;
}
});
To try and answer your questions directly:
Question 1:
Q: How do I correctly use customer renderers to paint specific cells in a JTable?
A: Your current code is setting a Renderer on the JTableHeader. To add a Renderer on your table cells would be similar code to what's above, only you'd set it through the Column model:
table.getColumnModel().getColumn(0).setCellRenderer(new DefaultTableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
// Set your code to render your component.
return renderer;
}
});
Note about this: JTables are column-based, which means that all the data in a certain column must be the same type (your SSCCE follows this convention). My favorite thing to do is to provide a custom Renderer for each type. For example, whenever I have a Date column, I use this renderer:
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import org.joda.time.LocalDate;
/**
*
* #author Ryan
*/
public class DateCellRenderer extends DefaultTableCellRenderer {
String pattern;
public DateCellRenderer(String pattern){
this.pattern = pattern;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value != null && value instanceof LocalDate) {
renderer.setText(((LocalDate)value).toString(pattern));
} else
throw new IllegalArgumentException("Only supported Object type is LocalDate.");
return renderer;
}
}
And I call this code with something similar:
table.getColumn("Date Entered").setCellRenderer(new DateCellRenderer("MMM dd, yyyy"));
Question 2:
Q: particular one table header color java swing
A: Umm.. Your SSCCE seems to have it figured out.
Question 3:
Q: about super.getTableCellRendererComponent(...) must be last code line before returns, I'm not able to write correct Renderer by those suggestion, for me works only this way
A: I'm not sure what you mean "must be last code line before returns." That is not the case, proven by the code snip I gave above
Question 4:
Q: JLabel is added for Borders, HorizontalAlignment and Foreground, especially Background caused me a few non_senses by using Component instead of JLabel, (not important here somehow)
A: Ok... the DefaultTableCellHeaderRenderer is sufficient for all of those, borders, alignment, foreground and background.
I had this happen to me in the past and I was convinced it had to do with the Cell Renderer, but the ArraysXxxException kind of Exceptions hunted me because I had forgotten to unselect and stop editing the cell before adding/removing rows. You should try clearSelection() and table.getCellEditor().stopCellEditing(); on your JTable before remove/add and see if that solves your problem.
First, of course, make sure it is editing:
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}