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

1.4.0 REGRESSION: Moving last column of JTable causes invalid selection events

XMLWordPrintable

    • Fix Understood
    • x86
    • windows_2000

      Name: gm110360 Date: 08/01/2002


      FULL PRODUCT VERSION :
      java version "1.4.0"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
      Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 Server
      Version 5.0.2195 Service Pack 2 Build 2195

      A DESCRIPTION OF THE PROBLEM :
      Moving the last column within a JTable while column is
      selected causes selection change events (valueChanged)to
      refer to non-existent column (and yes, I do supply a code
      fix).

      REGRESSION. Last worked in version 1.3.1

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Listen to selection changes in a JTable column and try
      to access the table's column using event.getLastColumn()
      2. Select the last column by clicking onto one of its
      fields (works even when column selection is not activated)
      3. Move the last column to the left

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The selection change event caused by moving the column
      should be received BEFORE the moving column is temporarily
      removed (in order to reinsert it at a new position) from
      the table's column model.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.lang.ArrayIndexOutOfBoundsException: 4 >= 4
      at java.util.Vector.elementAt(Vector.java:427)
      at javax.swing.table.DefaultTableColumnModel.getColumn
      (DefaultTableColumnModel.java:277)
      at TableBugDemo$1.valueChanged(TableBugDemo.java:88)
      at javax.swing.DefaultListSelectionModel.fireValueChanged
      (DefaultListSelectionModel.java:187)
      at javax.swing.DefaultListSelectionModel.fireValueChanged
      (DefaultListSelectionModel.java:167)
      at javax.swing.DefaultListSelectionModel.fireValueChanged
      (DefaultListSelectionModel.java:214)
      at javax.swing.DefaultListSelectionModel.removeIndexInterval
      (DefaultListSelectionModel.java:544)
      at javax.swing.table.DefaultTableColumnModel.moveColumn
      (DefaultTableColumnModel.java:180)
      at
      javax.swing.plaf.basic.BasicTableHeaderUI$MouseInputHandler.mouseDragged
      (BasicTableHeaderUI.java:191)
      at java.awt.AWTEventMulticaster.mouseDragged
      (AWTEventMulticaster.java:257)
      at java.awt.Component.processMouseMotionEvent(Component.java:5069)
      at javax.swing.JComponent.processMouseMotionEvent(JComponent.java:2763)
      at java.awt.Component.processEvent(Component.java:4822)
      at java.awt.Container.processEvent(Container.java:1380)
      at java.awt.Component.dispatchEventImpl(Component.java:3526)
      at java.awt.Container.dispatchEventImpl(Container.java:1437)
      at java.awt.Component.dispatchEvent(Component.java:3367)
      at java.awt.LightweightDispatcher.retargetMouseEvent
      (Container.java:3214)
      at java.awt.LightweightDispatcher.processMouseEvent(Container.java:2946)
      at java.awt.LightweightDispatcher.dispatchEvent(Container.java:2859)
      at java.awt.Container.dispatchEventImpl(Container.java:1423)
      at java.awt.Window.dispatchEventImpl(Window.java:1566)
      at java.awt.Component.dispatchEvent(Component.java:3367)
      at java.awt.EventQueue.dispatchEvent(EventQueue.java:445)
      at java.awt.EventDispatchThread.pumpOneEventForHierarchy
      (EventDispatchThread.java:190)
      at java.awt.EventDispatchThread.pumpEventsForHierarchy
      (EventDispatchThread.java:144)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
      at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:130)
      at java.awt.EventDispatchThread.run(EventDispatchThread.java:98)
      Trying to access Column 4...


      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import javax.swing.*;
      import javax.swing.event.*;
      import javax.swing.table.*;
      import java.awt.*;
      import java.awt.event.*;

      /**
       * TableBugDemo (derived from SimpleTableDemo)
       * demonstrates two different bugs within J2SE 1.4.0-b92
       * that may easily be fixed:
       *
       * 1. TableCellEditor not removed when leaving JTable for
       * second and subsequent time(s).
       *
       * 2. getLastIndex points to non-existent column in
       * ListSelectionListener.valueChanged when last column
       * is moved while being selected.
       *
       * ###@###.### 09-jun-02
       */

      public class TableBugDemo extends JFrame {

        private final JTable table;
        private final JScrollPane scrollPane;
        private final JPanel panel;
        private final JTextField textField;
        private final TableColumnModel tcm;
        private final ListSelectionModel tcsm;

        public TableBugDemo() {
          super("TableBugDemo");

          Object[][] data = {
            {"Mary", "Campione",
               "Snowboarding", new Integer(5), new Boolean(false)},
            {"Alison", "Huml",
               "Rowing", new Integer(3), new Boolean(true)},
            {"Kathy", "Walrath",
               "Chasing toddlers", new Integer(2), new Boolean(false)},
            {"Mark", "Andrews",
               "Speed reading", new Integer(20), new Boolean(true)},
            {"Angela", "Lih",
               "Teaching high school", new Integer(4), new Boolean(false)}
          };

          String[] columnNames = {"First Name",
                                  "Last Name",
                                  "Sport",
                                  "# of Years",
                                  "Move me after clicking false"};

          table = new JTable(data, columnNames);
          table.setPreferredScrollableViewportSize(new Dimension(800, 90));
          table.setCellSelectionEnabled(true); // Cosmetic only, errors anyway

          //Create the scroll pane and add the table to it.
          scrollPane = new JScrollPane(table);


          //Create a panel to hold the table's scrollpane and a textfield
          panel = new JPanel(new BorderLayout());

          //Add the scrollpane
          getContentPane().add(scrollPane, BorderLayout.CENTER);

          //Create and add a textfield to demonstrate focus change behaviour
          textField = new JTextField("Click here after double-clicking Mary " +
                                     "to cause Mary's editor to be removed. " +
                                     "Then repeat procedure again to find " +
                                     " that Mary now remains in edit state.");
          getContentPane().add(textField, BorderLayout.SOUTH);

          // Get the table's column model
          tcm = table.getColumnModel();
          // and it's selction model as well
          tcsm = tcm.getSelectionModel();

          // listenen to column selection changes
          tcsm.addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
              final int colNo = e.getLastIndex();
              System.out.println("Trying to access Column " + colNo + "...");

              // and now: java.lang.ArrayIndexOutOfBoundsException: 4 >= 4
              // when last column is moved while being selected
              final TableColumn tc = tcm.getColumn(colNo);
              System.out.println("... named " + tc.getHeaderValue());
            }

          });

        }

        public static void main(String[] args) {
          TableBugDemo frame = new TableBugDemo();
          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); // 1.4
          frame.pack();
          frame.setVisible(true);
        }
      }

      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      This is both a code fix and a workaround (when used
      properly subclassing
      javax.swing.table.DefaultTableColumnModel):

      public void moveColumn(int columnIndex, int newIndex)
        within class in javax.swing.table.DefaultTableColumnModel

      ...
      aColumn = (TableColumn)tableColumns.elementAt(columnIndex);

      tableColumns.removeElementAt(columnIndex);
      boolean selected = selectionModel.isSelectedIndex
      (columnIndex);
      selectionModel.removeIndexInterval(columnIndex,columnIndex);

      tableColumns.insertElementAt(aColumn, newIndex);
      selectionModel.insertIndexInterval(newIndex, 1, true);
      ...

      should be changed to

      ...
      aColumn = (TableColumn)tableColumns.elementAt(columnIndex);

      // not yet tableColumns.removeElementAt(columnIndex);
      boolean selected = selectionModel.isSelectedIndex
      (columnIndex);
      selectionModel.removeIndexInterval(columnIndex,columnIndex);
      tableColumns.removeElementAt(columnIndex); // now

      tableColumns.insertElementAt(aColumn, newIndex);
      selectionModel.insertIndexInterval(newIndex, 1, true);
      ...

      Release Regression From : 1.3.1_04
      The above release value was the last known release where this
      bug was known to work. Since then there has been a regression.

      (Review ID: 148156)
      ======================================================================

            peterz Peter Zhelezniakov
            gmanwanisunw Girish Manwani (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Imported:
              Indexed: