Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4276226

Problem using setColumnIdentifiers()when there are more identifiers than columns

    XMLWordPrintable

Details

    • beta
    • generic
    • generic

    Description

      t.dispatchEventImpl(Component.java:1786)
              at java.awt.Container.dispatchEventImpl(Container.java:923)
              at java.awt.Component.dispatchEvent(Component.java:1713)
              at
      java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:1559)
              at java.awt.LightweightDispatcher.processMouseEvent(Container.java:1463)
              at java.awt.LightweightDispatcher.dispatchEvent(Container.java:1395)
              at java.awt.Container.dispatchEventImpl(Container.java:910)
              at java.awt.Window.dispatchEventImpl(Window.java:492)
              at java.awt.Component.dispatchEvent(Component.java:1713)
              at java.awt.EventDispatchThread.run(EventDispatchThread.java:83)
      (Review ID: 100723)
      ======================================================================


      Name: krT82822 Date: 09/28/99


      9/28/99 eval1127@eng -- suspect this has already been fixed, but am filing bug just in case.

      I found a problem when I trying to set the column identifiers on a table model.
      The problem occurred when the number of columns identifiers supplied to a
      DefaultTableModel object is bigger than the actual number of columns in the Model.

      According to the API documentation, new columns are added to the Model, and this seems
      to happen, but displaying the Table and trying to visualise the added columns, a java.lang.ArrayIndexOutOfBoundsException
      is thrown.


      Execute the next application:

      import java.awt.*;
      import java.awt.event.*;
      import javax.swing.*;
      import javax.swing.event.*;
      import javax.swing.table.*;

      public class Main extends JFrame
      {
          
          JTable Table = null;
          DefaultTableModel TModel = null;
          JScrollPane SPanel = null;
          
          
          public Main(){
              this.super();
             
              // Here I set the number of columns in the Table to be 5
              
              TModel = new DefaultTableModel(5,5);
              Table = new JTable(TModel);
            
              
              SPanel = new JScrollPane(Table);
              
              this.getContentPane().add(SPanel,BorderLayout.CENTER);
              this.setSize(200,100);
              this.setVisible(true);
             
              String[] Headers ={"Column_1","Column_2","Column_3","Column_4","Column_5","Column_6"};
             
              // I set the column identifiers with 6 identifiers, the table has only 5 columns.
              // According to the API documentation. If the number of new Identifiers is greater than the current
              // numColumns, new columns are added to the end of each row in the model. If the number of
              // newIdentifier is less than the current number of columns, all the extra columns at the end of row //are
              // discarded.
              // this is true, One more columns is given to the Table, but when it is made
              // visible or you try to access it, and java.lang.ArrayIndexOutOfBoundsException is Thrown.
              
              // the solution to this problem is to add new columns manually using
              // methode TModel.addColumn(Object)

             
             
             TModel.setColumnIdentifiers(Headers);
              
              this.addWindowListener(new WindowAdapter(){
                  public void windowClosing(WindowEvent we){
                      System.exit(0);
                  }
                 });
              
          }
          
          public static void main(String[] argv){
              Main m = new Main();
          }
          
      }


      then trying to resize the window.

      At this point exception java.lang.ArrayIndexOutOfBoundsExceptionis thrown.

      the output of the command java -version is:

      java version "1.2"
      Classic VM N (build JDK-1.2-V native threads)

      the output of java -fullversion is:

      JAVA.EXE full version "JDK-1.2-V"

      The operative system is Windows 95; and I am NOT compling to native code.
      (Review ID: 95827)
      ======================================================================

      Name: krT82822 Date: 02/07/2000


      java version "1.2.2"
      HotSpot VM (1.0.1, mixed mode, build f)

        Description:
      DefaultTableModel.setColumnIdentifiers() does not seem to be working properly.
      It is supposed to truncate or add columns, if the column count is not equal to
      the number of column identifiers. It does adjust the columnCount, so if
      getColumnCount() is called, the correct number is returned. It does not actually
      adjust the elements in dataVector, until a row is added. At that point, the
      Vectors of the dataVector will be the correct size. If setColumnIdentifiers()
      is called again, increasing the identifiers size by 1, the Vectors of dataVector
      will have one less element than expected, and an ArrayOutOfBoundsException
      occurs, when calling setValue or getValue on the last column.

      A work around, as found in inner class MyModel, is to override
      setColumnIdentifiers, to adjust the DefaultTableModel.dataVector size, if
      necessary.

      Source Code: (Please observe the workaround in inner class, MyModel, commented
      out here). Press the 'Add Header/Column' button to observe the bug.

      ///////////////////////////////////////////////////////////////////
      //
      // File Name : Test2.java
      // Author : KM
      // Purpose : Test program to find a Java bug in the DefaultTableModel class.
      // DefaultTableModel.setColumnIdentifiers() does not seem to be
      // working properly. It is suppose to truncate or add columns,
      // if the column count is not equal to the number of
      // column identifiers. It does adjust the columnCount, so if
      // getColumnCount() is called, the correct number is returned.
      // It does not actually adjust the elements in dataVector,
      // until a row is added. At that point, the Vectors of the
      // dataVector will be the correct size. If setColumnIdentifiers()
      // is called again, increasing the identifiers size by 1,
      // the Vectors of dataVector will have one less element than
      // expected, and an ArrayOutOfBoundsException occurs, when calling
      // setValue or getValue on the last column.
      // A work around, as found in inner class MyModel, is to override
      // setColumnIdentifiers to adjust the DefaultTableModel.dataVector
      // size, if necessary.
      //
      ///////////////////////////////////////////////////////////////////
      import java.awt.*;
      import java.awt.event.*;
      import java.util.*;
      import javax.swing.*;
      import javax.swing.table.*;

      public class Test2 extends JFrame{
        public Test2(){
          try{
            getContentPane().setLayout(new BorderLayout());
            table = new MyTable();
            table.setAutoCreateColumnsFromModel(false);
            model = new MyModel();
            table.setModel(model);
            colModel = new DefaultTableColumnModel();
            table.setColumnModel(colModel);
            String[] columnHeaders= { "Header 1", "Header 2", "Header 3"};
            model.setColumnIdentifiers(columnHeaders);
            for (int i = 0; i < 3; i++){
              TableColumn col = new TableColumn(i);
              col.setHeaderValue(model.getColumnName(i));
              colModel.addColumn(col);
            }

            System.out.println("After adding three headers: ");
            table.debug();
            System.out.println(" ");

            for (int i=0; i < 3; i++){
              Object[] row = { "val1", "val2", "val3"};
              model.addRow(row);
            }

            table.debug();
            JButton b = new JButton("Add Header/Column");
            b.addActionListener(new AddColumnListener());
            table.setPreferredScrollableViewportSize(new Dimension(500, 70));
            JScrollPane scrollPane = new JScrollPane(table);
            getContentPane().add(scrollPane, BorderLayout.NORTH);
            
            JPanel p = new JPanel();
            p.add(b);
            getContentPane().add(p, "Center");
            
          }
          catch(Exception e){
            System.out.println("Test2.Test2() " + e.getMessage());
            e.printStackTrace();
          }
        }


        ///////////////////////////////////////////////////////////////////
        //
        // MyTable, inner class of Test2
        // Author : KM
        // Purpose : extend JTable, in order to provide debugging methods.
        //
        ///////////////////////////////////////////////////////////////////
        public class MyTable extends JTable{
          public MyTable(){
            super();
          }

          ///////////////////////////////////////////////////////////////////
          //
          // debug()
          // Author : KM
          // Purpose : write out info about the headers, model's row and column
          // count, the model's dataVector sizes, and the colModel's
          // column count.
          ///////////////////////////////////////////////////////////////////
          public void debug(){
            String err = "";
            String s = "";
            try{
              System.out.println("DEBUGGING: ");
              System.out.println("model # (row, cols): " + "(" + model.getRowCount() +
      "," + model.getColumnCount() + ")");
              Vector v = model.getDataVector();
              int z = -1;
              if (v.size() > 0)
                z = ((Vector)v.elementAt(0)).size();
              System.out.println("model vector length (row, cols): " + "(" + v.size()
      + "," + z + ")");
              System.out.println("model column model # cols: " +
      colModel.getColumnCount());
              System.out.print(" ");

              // print #'s for columns
              for (int i=0; i < model.getColumnCount(); i++){
                System.out.print(formatDebugString(String.valueOf(i)));
              }
              System.out.println("");

              // print column names
              System.out.print(" ");
              for (int i=0; i < model.getColumnCount(); i++){
                err = "Crapped out on header: " + i;
                s = model.getColumnName(i).trim();
                System.out.print(formatDebugString(s));
              }
              System.out.println(" ");

              // print values
              for (int i=0; i < model.getRowCount(); i++){
                // print row #
                System.out.print(i + " ");
                for (int j=0; j < model.getColumnCount(); j++){
                  err = "Crapped out on row, col: (" + i + "," + j + ")";
                  Object o = model.getValueAt(i, j);
                  if (o == null)
                    s = "null";
                  else
                    s = o.toString();
                  System.out.print(formatDebugString(s));
                }
                System.out.println("");
              }
              System.out.println(" ");
            }
            catch(Exception e){
              System.out.println(" ");
              System.out.println("MyTable.debug() Exception : " + e);
              System.out.println("Error message: " + err);
              e.printStackTrace();
            }
          }
          
          ///////////////////////////////////////////////////////////////////
          //
          // formatDebugString()
          // Author : KM
          // Purpose : format the debug string so it is exactly 10 charactes +
          // " | ". This way the columns will line up.
          ///////////////////////////////////////////////////////////////////
          private String formatDebugString(String s) throws Exception{
            try{
              if (s == null)
                s = "NULL";
              if (s.equals(""))
                s = "EMPTY_STR";
              // make string exactly 10 chars long
              while (s.length() < 10){
                s += " ";
              }
              if (s.length() > 10){
                s = s.substring(0, 9) + "+";
              }
              s += " | ";
            }
            catch(Exception e){
              System.out.println("Matrix.formatDebugString() Exception: " + e);
              System.out.println("throwing back to caller");
              throw(e);
            }
            return s;
          }
        }

        ///////////////////////////////////////////////////////////////////
        //
        // MyModel, inner class of Test2
        // Author : KM
        // Purpose : Extend DefaultTableModel and override
        // setColumnIdentifiers to adjust the size of the dataVector,
        // if necessary. This is a workaround for a Java bug, in-progress.
        //
        ///////////////////////////////////////////////////////////////////
        public class MyModel extends DefaultTableModel{
          public MyModel(){
            super();
          }

          // THIS IS THE WORK AROUND, UNCOMMENT AFTER OBSERVING THE BUG
          /* public void setColumnIdentifiers(Object[] identifiers){
            super.setColumnIdentifiers(identifiers);
            if (dataVector.size() > 0){
              // rows have been added, check for the size of the row Vectors being
              // less than that of the column count, and, if necessary,
              // add elements to each row Vector
              if (((Vector)dataVector.elementAt(0)).size() < getColumnCount()){
                for (int i=0; i < dataVector.size(); i++){
                  Vector rowVector = (Vector)dataVector.elementAt(i);
                  int colsNeeded = getColumnCount() - rowVector.size();
                  for (int j=0; j < colsNeeded; j++){
                    // null is the default value in DefaultTableModel
                    rowVector.addElement(null);
                  }
                }
              }
            }
          }
          */
        }

        ///////////////////////////////////////////////////////////////////
        //
        // AddColumnListener, inner class of Test2
        // Author : KM
        // Purpose : Test resetting the column identifiers and adding a column,
        // to the data model.
        //
        ///////////////////////////////////////////////////////////////////
        public class AddColumnListener implements ActionListener{
          public AddColumnListener(){

          }
          
          public void actionPerformed(ActionEvent e){
            String[] headers = new String[model.getColumnCount() + 1];
            for (int i = 0; i < model.getColumnCount(); i++)
              headers[i] = model.getColumnName(i);

            headers[headers.length - 1] = "New Header " + headers.length;
            model.setColumnIdentifiers(headers);
            for (int i=0; i < model.getColumnCount() - 1; i++){
              TableColumn col = colModel.getColumn(i);
              col.setHeaderValue(model.getColumnName(i));
            }
            table.debug();

            TableColumn col = new TableColumn(headers.length - 1);
            col.setHeaderValue(model.getColumnName(headers.length - 1));
            colModel.addColumn(col);
          }
        }
          
        public static void main(String args[]){
          Test2 t = new Test2();
          t.setSize(600, 600);
          t.setVisible(true);
        }

        MyTable table;
        MyModel model;
        DefaultTableColumnModel colModel;
       
      }

      Output:
      DEBUGGING:
      model # (row, cols): (0,3)
      model vector length (row, cols): (0,-1)
      model column model # cols: 3
        0 | 1 | 2 |
        Header 1 | Header 2 | Header 3 |
        
       
      DEBUGGING:
      model # (row, cols): (3,3)
      model vector length (row, cols): (3,3)
      model column model # cols: 3
        0 | 1 | 2 |
        Header 1 | Header 2 | Header 3 |
      0 val1 | val2 | val3 |
      1 val1 | val2 | val3 |
      2 val1 | val2 | val3 |
        
      DEBUGGING:
      model # (row, cols): (3,4)
      model vector length (row, cols): (3,3)
      model column model # cols: 3
        0 | 1 | 2 | 3 |
        Header 1 | Header 2 | Header 3 | New Heade+ |
      0 val1 | val2 | val3 |
      MyTable.debug() Exception : java.lang.ArrayIndexOutOfBoundsException: 3 >= 3
      Error message: Crapped out on row, col: (0,3)
      java.lang.ArrayIndexOutOfBoundsException: 3 >= 3
              at java.util.Vector.elementAt(Vector.java)
              at
      javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:600)
              at Test2$MyTable.debug(Test2.java:130)
              at Test2$AddColumnListener.actionPerformed(Test2.java:240)
              at
      javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1066)
              at
      javax.swing.AbstractButton$ForwardActionEvents.actionPerformed(AbstractButton.ja
      va:1101)
              at
      javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:378)
              at
      javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:250)
              at
      javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.jav
      a:204)
              at java.awt.Component.processMouseEvent(Component.java:2409)
              at java.awt.Component.processEvent(Component.java:2254)
              at java.awt.Container.processEvent(Container.java:878)
              at java.awt.Componen

      Attachments

        Activity

          People

            pmilnesunw Philip Milne (Inactive)
            kryansunw Kevin Ryan (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: