• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 475
  • Last Modified:

Sortable table paint problem arrayout of bounds

I have a Sortable jtable.  The first time that data is added to it, it loads up just fine.  I have an update button (basically, the user select certain criteria and the data is displayed in the jtable when they click update).  This works fine.  When i click the headers the jtable's data is displaying fine and sorting properly.   The problem is after sorting the jtable several times and then clicking update it throws the following error (seems to throw it for every row being added) and leaving the row blank, then after all rows have been added, all the data is displayed properly in the jtable (or it appears to be correct)

If it helps i am using the jtable example, but have altered the executing code slightly so that I can add data anytime instead of just once when the dialog is displayed:
http://www.objects.com.au/java/examples/swing/SortableTable.do

Error:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 40 >= 40
      at java.util.Vector.elementAt(Vector.java:432)
      at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:621)
      at table.SortableTableModel.getValueAt(SortableTableModel.java:17)
      at javax.swing.JTable.getValueAt(JTable.java:1852)
      at javax.swing.JTable.prepareRenderer(JTable.java:3907)
      at javax.swing.plaf.basic.BasicTableUI.paintCell(BasicTableUI.java:1985)
      at javax.swing.plaf.basic.BasicTableUI.paintCells(BasicTableUI.java:1887)
      at javax.swing.plaf.basic.BasicTableUI.paint(BasicTableUI.java:1810)
      at javax.swing.plaf.ComponentUI.update(ComponentUI.java:154)
      at javax.swing.JComponent.paintComponent(JComponent.java:742)
      at javax.swing.JComponent.paint(JComponent.java:1005)
      at javax.swing.JComponent.paintChildren(JComponent.java:842)
      at javax.swing.JComponent.paint(JComponent.java:1014)
      at javax.swing.JViewport.paint(JViewport.java:726)
      at javax.swing.JComponent.paintChildren(JComponent.java:842)
      at javax.swing.JComponent.paint(JComponent.java:1014)
      at javax.swing.JComponent._paintImmediately(JComponent.java:4881)
      at javax.swing.JComponent.paintImmediately(JComponent.java:4667)
      at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:477)
      at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:114)
      at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
      at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:275)
      at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:196)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:190)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:182)
      at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)

Has anyone ran into this issue before?
0
tbboyett
Asked:
tbboyett
  • 4
  • 2
1 Solution
 
Mayank SAssociate Director - Product EngineeringCommented:
>> but have altered the executing code slightly

What is that?
0
 
tbboyettAuthor Commented:
my appologies, i meant the code that sets up the jtable headers and adds data, renderers and so forth.
I'll post the way that i'm doing this in just a sec so that you can compare
0
 
tbboyettAuthor Commented:
// My way

SortableTableModel zipsTM = new SortableTableModel() {
        public Class getColumnClass(int col) {
            switch (col) {
            case 0:
                return Double.class;
            case 1:
                return String.class;
            case 2:
                return String.class;
            case 3:
                return Integer.class;
            case 4:
                return Integer.class;
            default:
                return Object.class;
            }
        }

        public boolean isCellEditable(int row, int col) {
            switch (col) {
            case 1:
                return false;
            default:
                return true;
            }
        }

        public void setValueAt(Object obj, int row, int col) {
            switch (col) {
            case 2:
                super.setValueAt(new Integer(obj.toString()), row, col);
                return;
            default:
                super.setValueAt(obj, row, col);
                return;
            }
        }
};
JTable zipsJT = new JTable(zipsTM);
Vector zipsheaders = new Vector();
zipsheaders.addElement("Distance");
zipsheaders.addElement("Direction");
zipsheaders.addElement("City");
zipsheaders.addElement("Zip");
zipsheaders.addElement("Count");

SortButtonRenderer renderer = new SortButtonRenderer();
TableColumnModel model = zipsJT.getColumnModel();

JTableHeader header = zipsJT.getTableHeader();
header.addMouseListener(new HeaderListener(header, renderer));

((SortableTableModel) zipsJT.getModel()).setColumnIdentifiers(zipsheaders);
SortableTableModel t = (SortableTableModel) zipsJT.getModel();
t.setRowCount(0);
int []zipwidths = {80, 80, 150, 50, 70};

int n = zipsheaders.size();
for (int i = 0; i < n; i++) {
     model.getColumn(i).setHeaderRenderer(renderer);
     model.getColumn(i).setPreferredWidth(zipwidths[i]);
}

// The examples way

String[] headerStr = {"Name","Date","Size","Dir"};
    int[] columnWidth = {100,150,100,50};
   
    SortableTableModel dm = new SortableTableModel() {
      public Class getColumnClass(int col) {
        switch (col) {
          case  0: return String.class;
          case  1: return Date.class;
          case  2: return Integer.class;
          case  3: return Boolean.class;
          default: return Object.class;
        }
      }
      public boolean isCellEditable(int row, int col) {
        switch (col) {
          case  1: return false;
          default: return true;
        }
      }  
      public void setValueAt(Object obj, int row, int col) {
        switch (col) {
          case  2: super.setValueAt(new Integer(obj.toString()), row, col); return;
          default: super.setValueAt(obj, row, col); return;
        }
      }
    };
    dm.setDataVector(new Object[][]{
      {"b"   ,getDate("98/12/02"),new Integer(14),new Boolean(false)},
      {"a"   ,getDate("99/01/01"),new Integer(67),new Boolean(false)},
      {"d"   ,getDate("99/02/11"),new Integer(2) ,new Boolean(false)},
      {"c"   ,getDate("99/02/27"),new Integer(7) ,new Boolean(false)},
      {"foo" ,new Date()         ,new Integer(5) ,new Boolean(true)},
      {"bar" ,new Date()         ,new Integer(10),new Boolean(true)}},
      headerStr);
     
    JTable table = new JTable(dm);
    //table.setShowGrid(false);
    table.setShowVerticalLines(true);
    table.setShowHorizontalLines(false);
    SortButtonRenderer renderer = new SortButtonRenderer();
    TableColumnModel model = table.getColumnModel();
    int n = headerStr.length;
    for (int i=0;i<n;i++) {
      model.getColumn(i).setHeaderRenderer(renderer);
      model.getColumn(i).setPreferredWidth(columnWidth[i]);
    }
   
    JTableHeader header = table.getTableHeader();
    header.addMouseListener(new HeaderListener(header,renderer));


If you notice in the examples code, you have to add the data to the model then create the jtable.
I needed to be able to add data later and change it when needed.

When I add data, this is how i do it:
SortableTableModel z = (SortableTableModel) zipsJT.getModel();
z.setNumRows(0);

Vector ziprow = new Vector();
ziprow.addElement(new Double(format.format(czc.distance)));
ziprow.addElement(czc.direction);
ziprow.addElement(czc.city);
ziprow.addElement(new Integer(czc.zip));
ziprow.addElement(new Integer(czc.count));
z.addRow(ziprow);

Like i say it works perfect the first time, the problem just happens if i sort the table and then readd data
I hope this helps
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
tbboyettAuthor Commented:
if i use this code to to call the method it works fine except it doesn't update the progressbar and labels as it normally would:

Runnable runnable = new Runnable() {
public void run() {
        loadzipsTable();  
}
};
EventQueue.invokeLater(runnable);

I tried:

try {
        EventQueue.invokeLater(new ProgressUpdater(line, numlines));
} catch (Exception e) {
      e.printStackTrace();
}

to update the progressbar but it throws:
Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread

can someone explain the reason why?
0
 
objectsCommented:
Reason for your original problem is that you were updating your table from a different thread, Swing is single threaded so all calls need to be made from event dispatch thread.

> it doesn't update the progressbar and labels as it normally would:

can u post the code that updates the progress and labels

> Exception in thread "AWT-EventQueue-0" java.lang.Error: Cannot call invokeAndWait from the event dispatcher thread

you can only use invokeLater() from the edt.
0
 
tbboyettAuthor Commented:
Here is how i update the labels  
try {
     EventQueue.invokeAndWait(new ProgressLblUpdater("Doing some long process"));
} catch (Exception e) {
     e.printStackTrace();
}

private class ProgressLblUpdater implements Runnable {
      private String text;

      public ProgressLblUpdater(String text) {
        this.text = text;
      }

      public void run() {
          actionLbl.setText(text);
      }
}

Here is how i update the progressbar
try {
     EventQueue.invokeAndWait(new ProgressUpdater(line, numlines));
} catch (Exception e) {
     e.printStackTrace();
}


private class ProgressUpdater implements Runnable {
      private int line, numlines;

      public ProgressUpdater(int line, int numlines) {
          this.line = line;
          this.numlines = numlines;
      }

      public ProgressUpdater(int line, int numlines) {
        this.line = line;
        this.numlines = numlines;
      }

      public void run() {

         pbar.setMaximum((numlines));
         pbar.setValue(line);
      }
    }
0
 
objectsCommented:
>      EventQueue.invokeAndWait(new ProgressLblUpdater("Doing some long process"));

change to:

new ProgressLblUpdater("Doing some long process").run();

and:

>      EventQueue.invokeAndWait(new ProgressUpdater(line, numlines));

to:

     new ProgressUpdater(line, numlines).run();

or just update them directly without create Runnable instance.
0

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now