3

I'm quite sure this problem has a simple solution, but I haven't been able to solve it.

Scenario:

1) I have a JTable linked to a model based on a LinkedHashMap with (for example) 10 elements.

2) External events delete the first 2 elements almost at the same time, so:

2.1) The model deletes element #0, and throws an event like "row linked to element #0, it is, row #0, has changed".

2.2) Before the JTable has time to be modified, the second element is deleted on the model and the event launched is the same, because the second element is now the first one.

3) The JTable processes both events "row #0 has been deleted".

I think this is why I am getting a "NULL error" like the following one:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at paneles.panel_positions.Elements_Manager.getValueAt(Elements_Manager.java:388)
    at paneles.panel_positions.Elements_Manager$1Dates_Renderer.getTableCellRendererComponent(Positions_Manager.java:891)
    at javax.swing.JTable.prepareRenderer(JTable.java:5736)
    at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:2114)
    at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:2016)
    at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1812)
    at javax.swing.plaf.ComponentUI.update(ComponentUI.java:161)
    at javax.swing.JComponent.paintComponent(JComponent.java:778)
    at javax.swing.JComponent.paint(JComponent.java:1054)
    at javax.swing.JComponent.paintChildren(JComponent.java:887)
    at javax.swing.JComponent.paint(JComponent.java:1063)
    at javax.swing.JViewport.paint(JViewport.java:731)
    at javax.swing.JComponent.paintChildren(JComponent.java:887)
    at javax.swing.JComponent.paint(JComponent.java:1063)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5230)
    at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:295)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1249)
    at javax.swing.JComponent._paintImmediately(JComponent.java:5178)
    at javax.swing.JComponent.paintImmediately(JComponent.java:4989)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:808)
    at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
    at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
    at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
    at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1677)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:312)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

I've been thinking on any kind of synchronized mechanism so the second deletion can't be executed until the first one had been finished and executed the event on the JTable, but I can't figure it out which would be the correct way of doing this.

This is happening on a real time-events-processing app, so forcing the events source to wait in this way doesn't seem to be a good solution, but I can't figure it out a correct way of doing it. Any idea?

Thanks in advance.

EDIT:

Method on another thread that launches deletions:

public void delete_all_elements() {

cloned_model = mainobject.getCloned_model();

for (Element pos_aux : cloned_model.values()) {
        notify_pos_to_be_deleted(pos_aux);
    }
}

Code executed on the thread wich receives the previous message on a messages-queue:

...
model.rmv(row_index);
TableModelEvent event = new TableModelEvent (this, row_index, total_rows-1, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE);
notify_suscriptors(event);
...

Code of notify_suscriptors:

...
((TableModelListener)listeners.get(i)).tableChanged(event);
...
Alberto Martín
  • 439
  • 13
  • 26

1 Answers1

2

You must update your Table Model only on the event dispatch thread. Use EventQueue.invokeLater(), as shown in this related example.

EventQueue.invokeLater(new Runnable() {

    @Override
    public void run() {
        // remove row
    }
});
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Ok, so, if I've got it right, the thread wich makes the model modification, wich right now is a simple "Runnable" with a while waiting for new orders, should be modified in the way you show me. Sounds like it could work; I'll try it right now. – Alberto Martín Jan 18 '15 at 06:47
  • Now I'm detecting an unexpected increment on the RAM used by the main app (not an alarming one (179MB -> 184MB), just not understood at this moment, I'll have to study it), but the problem with the NULL pointer has been solved. Perfectly solved trashgod, thanks a lot!!! – Alberto Martín Jan 18 '15 at 07:08
  • 2
    Glad to help; using a [profiler](http://stackoverflow.com/q/2064427/230513) may be helpful; `DefaultTableModel` may be a [problem](http://stackoverflow.com/a/25526869/230513). – trashgod Jan 18 '15 at 07:19
  • Great. Another deserved +1 on your http://stackoverflow.com/questions/6309407/remove-top-level-container-on-runtime helping answer :) – Alberto Martín Jan 18 '15 at 07:35