0

Hi have a Jtable with a specific cell rendered model for one column. This model, just put buttons in this column instead of text data.

The first display of the table works well. WHen I'm using a function that change the order of the content, the model is still called for this column (the redraw is forced through a call to fireTableDataChanged()).

Now, I want that the delete key delete the current row of my table. For this, I'm using the following code:

public void keyTyped(KeyEvent arg0) {
    if (arg0.getKeyChar() == KeyEvent.VK_DELETE) {
        int currentRow = this.m_data.currentRow();
        if (currentRow >= 0) {
            this.m_data.deleteRow(currentRow);
            System.out.println("mise a jour après destruction de ligne");
            this.fireTableRowsDeleted(currentRow, currentRow);
        }
    }
}

(m_data is my table model). Surprisingly, the data are updated (row has disappeared), but the first column is empty. And my traces show that just getValueAt() are called. getTableCellRendererComponent() is not called.

I have tried to fire fireTableDataChanged() instead of fireTableRowsDeleted() but it is the same thing. Hence it does not seem to be relative to the fire function. Any idea about the origin of this problem, and the way to solve it?

Thanks in advance.

  • In fact, the problem is that, in this function the call to the function fireXXXX() has the side effect to remove all column formatting (width are resetted, and the buttons that I put in the first column disappear). –  Sep 07 '12 at 19:05

2 Answers2

1

This is the code we use for a table model. you can use it. It's pretty simple and clean as you can see.

            public abstract class BeanTableModel<B> extends ArrayList<B>
                    implements TableModel {

            private List<TableModelListener> listeners = new ArrayList();
            private TableModelAttributeList attributeList;

            public BeanTableModel() {
                super();
            }

            public BeanTableModel(Object[][] attributes) {
                super();
                this.attributeList = new TableModelAttributeList(attributes) {
                };
            }

            public TableModelAttributeList getAttributeList() {
                return attributeList;
            }

            public final void setAttributeList(TableModelAttributeList attributeList) {
                this.attributeList = attributeList;
            }

            @Override
            public final int getRowCount() {
                return size();
            }

            @Override
            public final int getColumnCount() {
                if (attributeList != null) {
                    return attributeList.size();
                } else {
                    return 0;
                }
            }

            @Override
            public final String getColumnName(int columnIndex) {
                if (attributeList != null) {
                    return attributeList.getColumnName(columnIndex);
                } else {
                    return null;
                }
            }

            @Override
            public final Class<?> getColumnClass(int columnIndex) {
                if (attributeList != null) {
                    return attributeList.getColumnClass(columnIndex);

                } else {
                    return Object.class;
                }
            }

            @Override
            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return false;
            }

            @Override
            public final Object getValueAt(int rowIndex, int columnIndex) {
                try {
                    if (rowIndex >= 0) {
                        return (attributeList != null) ? attributeList.getValue(this.get(
                                rowIndex), columnIndex) : null;
                    } else {
                        return get(rowIndex);
                    }
                } catch (Exception ex) {
                    Logger.getLogger(BeanTableModel.class.getName()).log(Level.SEVERE,
                                                                            null, ex);
                    return null;
                }
            }

            @Override
            public final boolean add(B e) {
                boolean result = super.add(e);

                if (result) {
                    fireListeners();
                }

                return result;
            }

            @Override
            public final boolean addAll(Collection<? extends B> c) {
                boolean result = super.addAll(c);

                if (result) {
                    fireListeners();
                }

                return result;
            }

            public final void change(Collection<? extends B> c) {
                super.clear();
                super.addAll(c);
                fireListeners();
            }

            @Override
            public final boolean addAll(int index, Collection<? extends B> c) {
                boolean result = super.addAll(index, c);

                if (result) {
                    fireListeners();
                }

                return result;
            }

            @Override
            public final void clear() {
                super.clear();
                fireListeners();
            }

            @Override
            public final boolean remove(Object o) {
                boolean result = super.remove(o);

                if (result) {
                    fireListeners();
                }

                return result;
            }

            @Override
            public final boolean removeAll(Collection<?> c) {
                boolean result = super.removeAll(c);

                if (result) {
                    fireListeners();
                }

                return result;
            }

            @Override
            protected final void removeRange(int fromIndex, int toIndex) {
                super.removeRange(fromIndex, toIndex);
                fireListeners();
            }

            @Override
            public final boolean retainAll(Collection<?> c) {
                boolean result = super.retainAll(c);

                if (result) {
                    fireListeners();
                }

                return result;
            }

            @Override
            public final B remove(int index) {
                B b = super.remove(index);
                fireListeners();
                return b;
            }

            @Override
            public final void add(int index, B element) {
                super.add(index, element);
                fireListeners();
            }

            @Override
            public final B set(int index, B element) {
                B b = super.set(index, element);
                fireListeners();
                return b;
            }

            @Override
            public final void trimToSize() {
                super.trimToSize();
                fireListeners();
            }

            @Override
            public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
                //Do Nothing
            }

            @Override
            public final void addTableModelListener(TableModelListener l) {
                listeners.add(l);
            }

            @Override
            public final void removeTableModelListener(TableModelListener l) {
                listeners.remove(l);
            }

            public final void fireListeners() {
                TableModelEvent evt = new TableModelEvent(this);

                for (TableModelListener listener : listeners) {
                    listener.tableChanged(evt);
                }
            }

            public final ArrayList<B> serialize() {
                return new ArrayList<B>(this);
            }
          }

This is for the format and how its interpreted:

            public abstract class TableModelAttributeList {

            public static final int COLUMN_NAME = 0;
            public static final int CLASS = 1;
            public static final int ATTRIBUTE_NAME = 2;
            public static final int FORMAT = 3;
            public static final int REPLACE = 4;
            private final Object[][] attributes;
            private final Pattern[] patterns;

            public TableModelAttributeList(Object[][] attributes) {
                this.attributes = attributes;
                patterns = new Pattern[attributes.length];

                for (int i = 0, size = attributes.length; i < size; i++) {
                    if (attributes[i][REPLACE] != null) {
                        patterns[i] = Pattern.compile((String) attributes[i][FORMAT]);
                    }
                }
            }

            public final String getColumnName(int column) {
                return (String) attributes[column][COLUMN_NAME];
            }

            public final Class<?> getColumnClass(int column) {
                return (Class<?>) attributes[column][CLASS];
            }

            public final int size() {
                return attributes.length;
            }

            public final Object getValue(Object bean, int column) throws
                    Exception {

                try {
                    Object value = null;

                    if (attributes[column][ATTRIBUTE_NAME] == null) {
                        return "";
                    }

                    if (attributes[column][ATTRIBUTE_NAME].equals("this")) {
                        return bean;

                    } else {
                        try {
                        value = PropertyUtils.getProperty(bean,
                                                            (String) attributes[column][ATTRIBUTE_NAME]);
                        } catch (NullPointerException ex) {
                        return "";

                        } catch (NestedNullException ex) {
                        return "";
                        }
                    }
                    if (value == null) {
                        return null;

                    } else if (patterns[column] != null) {
                        Matcher matcher = patterns[column].matcher(String.valueOf(value));
                        if (matcher.find()) {
                        return matcher.replaceAll(
                                (String) attributes[column][REPLACE]);
                        } else {
                        return null;
                        }

                    } else if (value instanceof Date) {
                        if (attributes[column][FORMAT] != null) {
                        DateFormat format = new SimpleDateFormat(
                                (String) attributes[column][FORMAT]);
                        return format.format((Date) value);

                        } else {
                        return value;
                        }

                    } else if (attributes[column][FORMAT] != null) {
                        return String.format(
                                (String) attributes[column][FORMAT], value);
                    } else {
                        return value;
                    }
                } catch (IllegalAccessException ex) {
                    String message = "The property named '"
                            + (String) attributes[column][ATTRIBUTE_NAME]
                            + "' has a private getter method";
                    throw new Exception(message, ex);
                } catch (InvocationTargetException ex) {
                    String message = "An exception has ocurred while retrieving value for bean property '"
                            + (String) attributes[column][ATTRIBUTE_NAME] + "'";
                    throw new Exception(message, ex);
                } catch (NoSuchMethodException ex) {
                    String message = "The bean doesn't have a property named '"
                            + (String) attributes[column][ATTRIBUTE_NAME] + "'";
                    throw new InvalidModelAttributesException(message, ex);
                }
            }
          }

This is how the table model should be created:

            public class SelectEmployeeTableModel extends BeanTableModel<Empleados> {

                public static final String NOMBRE = "Nombre";

                public static final String DEPARTAMENTO = "Departamento";

                public static final String FECHA_BAJA = "FechaBaja";

                public SelectEmployeeTableModel() {
                    super(new Object[][]{
                        {NOMBRE                   ,  Object.class,     "nombreCompleto"           , null, null},
                        {DEPARTAMENTO       ,  Object.class,     "departamentoId.nombre"    , null, null},
                        {FECHA_BAJA       ,  Object.class,     "fechaBaja"    , null, null}
                    });
                }
             }

the first column is the visible column name, the second is the type of the data (if you want to show a checkbox, replace it for a Boolean.class), the third is the name without the "get" prefix as it uses reflection, the fourth is the format (for a date it could be "dd/MM/yyyy" or "$%.2f" for a decimal number) and the fifth is for replace with reggex.

Then in the panel where you want to use it do this:

          jtable.setModel(new SelectEmployeeTableModel());

if you need to change the data in the table model you do

          model.change(collectionName);

and if you only wantit to refresh for some reason, you do

          model.fireListeners();

and the renderer never had fail. At less that you dont set the getter right in the entity.

if you have any doubt dont be afraid to ask! Have a great day.

JGutierrezC
  • 4,398
  • 5
  • 25
  • 42
  • Thanks. But this does not solve my problem that is I need a push button in column 0 and that the push buttons remain after the deletion of one row in response to the use of the DEL key. –  Sep 07 '12 at 07:35
  • nope, i still dont get it. i dont understand the problem i tought it was a problem for the data isnt deleted after you press supr :\ – JGutierrezC Sep 07 '12 at 14:07
0

OK, finally I found the problem. I had a ListSelectionListener, that, in somes circonstances, sent a fireTableCellUpdated(-1,0). This is this command that "stupid Java" interpreted as "remove the table rendering".