JDK-4813624 : JTable SelectionModel is out of sync, getSelectedRow() returning bad results
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.1
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2003-02-05
  • Updated: 2003-02-06
  • Resolved: 2003-02-06
Related Reports
Duplicate :  
Description

Name: jk109818			Date: 02/05/2003


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

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
Having a JTable with getRowCount()==0, navigating through
the Application with "Tab", brings the SelectionModel of
the JTable out of synch with the TableModel.
I guess, the
Method "BasicTableUI.NavigationalAction.moveWithinSelectedRange(..)" 
produces side effects to the Member "anchorRow"
which is then used to update the selection on line 186 of
BasicTableUI.

When the SelectionModel is out of synch, the Application
runs into Exceptions, when it tries something
like "tableModel.getValueAt(table.getSelectedRow(), 0)",
which should normally be safe, if "table.getSelectedRow()
>0".

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.Compile and run the attached Program
2.press "Tab" several times (the focus will be moved into
the Table first. After that, it tries to navigate inside
the Table (while there are no rows..)
3.

EXPECTED VERSUS ACTUAL BEHAVIOR :
Expected: System.out should have entries like
Selected Row = -1

Actual: There seems to be a selected row, and it is
counting up and up with every pressed "Tab"-Key...

Selected Row = 1
Selected Row = 2
Selected Row = 3


ERROR MESSAGES/STACK TRACES THAT OCCUR :
If I would do something with the value I got from getSelectedRow(), I could get
numerous Exceptions...

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;

public class Frame2 extends JFrame {
  private JPanel contentPane;
  private BorderLayout borderLayout1 = new BorderLayout();
  private JTextField jTextField1 = new JTextField();
  private JScrollPane jScrollPane1 = new JScrollPane();
  private JTable jTable1 = new JTable();
  private TableModel model = new DefaultTableModel(new String[]{""}, 0);
  protected ListSelectionListener myTableSelectionListener = new
ListSelectionListener(){
              public void valueChanged(ListSelectionEvent e){
                //if I would get data through the index provided by
                //getSelectedRow, an Exception would occur...
                System.out.println("Selected Row = "+ jTable1.getSelectedRow());
              }
            };

  //Construct the frame
  public Frame2() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    jTable1.setModel(model);
    jTable1.getSelectionModel().addListSelectionListener
(myTableSelectionListener);

  }
  //Component initialization
  private void jbInit() throws Exception  {
    contentPane = (JPanel) this.getContentPane();
    jTextField1.setText("jTextField1");
    contentPane.setLayout(borderLayout1);
    this.setSize(new Dimension(400, 300));
    this.setTitle("Frame Title");
    contentPane.add(jTextField1, BorderLayout.NORTH);
    contentPane.add(jScrollPane1, BorderLayout.CENTER);
    jScrollPane1.getViewport().add(jTable1, null);
  }
  //Overridden so we can exit when window is closed
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      System.exit(0);
    }
  }
  //Main method
  public static void main(String[] args) {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    Frame f = new Frame2();
    f.validate();
    f.setVisible(true);
  }
}
---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Overwrite JTable.changeSelection(..):

public void changeSelection(int rowIndex, int columnIndex,
boolean toggle, boolean extend) {
    if (!toggle && !extend){
      //the case which is buggy in the default
implementation...
      //comes
from "BasicTableUI.NavigationalAction.moveWithinSelectedRang
e(..)" which produces sideeffects
      int maxIndex = getRowCount()-1;
      if (maxIndex < rowIndex){
        rowIndex = maxIndex;//correction here...
      }
    }
    super.changeSelection(rowIndex, columnIndex, toggle,
extend);
}
(Review ID: 179054) 
======================================================================

Comments
EVALUATION This is a duplicate of 4801274. ###@###.### 2003-02-06
06-02-2003