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

JTable.getSelectedRow() fails with TableCellRenderer

XMLWordPrintable

      Name: jk109818 Date: 04/14/2003


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


      FULL OS VERSION :
      Windows 98 [Version 4.10.2222]


      A DESCRIPTION OF THE PROBLEM :
      When a JButton is used with a custom CellEditor and is mouse-clicked, then its row is not selected under these conditions:
      - The row of the clicked button is the same as that of the previously clicked button.
      - The table content was refreshed between the 2 button clicks.



      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Use the provided testcase.

      1) Click on button in row 3 (index 2)
      2) Click on button "Refresh"
      3) Go to 1)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The value selectedRow in the dialog should always be 2.

      The value selectedRow in the dialog is -1 and the table row is not selected.

      REPRODUCIBILITY :
      This bug can be reproduced always.

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

      public class SelectionLost extends javax.swing.JFrame{
          

          private boolean workaround = false;
          private int previousSelectedRow;
          final int columnCount = 2;
          String[] dataArray1 = new String[]{"0", "1", "2"};
          String[] dataArray2 = new String[]{"0", "1", "2", "3", "4"};
          String[] dataArray = dataArray1;
          // Provide a single button instance to be re-used for rendering all rows
          private final JButton renderButton = new JButton("...");
          // Provide a single button instance to be re-used for editing in all rows
          private final JButton clickButton = new JButton("...");

          
          
          public SelectionLost() {
              initComponents();
              TableCellRenderer buttonRenderer = new TableCellRenderer(){
                  public Component getTableCellRendererComponent(JTable table,
                         Object value,
                         boolean isSelected,
                         boolean hasFocus,
                         int row,
                         int column){
                      return renderButton;
                  }// method
              };// anon class

              jTable1.setDefaultRenderer(JButton.class, buttonRenderer);

              ButtonCellEditor buttonEditor = new ButtonCellEditor(clickButton);

              jTable1.setDefaultEditor(JButton.class, buttonEditor);

              clickButton.addActionListener(new java.awt.event.ActionListener() {
                  public void actionPerformed(java.awt.event.ActionEvent evt) {
                      int selectedRow = jTable1.getSelectedRow();
                      // The workaround exploits the fact that the bug only occurs
                      // when the selection is not changed: It uses the previous
                      // selection.
                      if(workaround){
                          if(selectedRow == -1){
                              selectedRow = previousSelectedRow;
                          }// if
                          else{
                              previousSelectedRow = selectedRow;
                          }// else
                      }// if
                      JOptionPane.showMessageDialog(null, "selectedRow = " + selectedRow);
                  }//method
              });
              

          }// constr

          public static void main(String args[]) {
              new SelectionLost().show();
          }

          private void initComponents() {
              jPanelTop = new javax.swing.JPanel();
              jButtonRefresh = new javax.swing.JButton();
              jScrollPane1 = new javax.swing.JScrollPane();
              jTable1 = new javax.swing.JTable();

              addWindowListener(new java.awt.event.WindowAdapter() {
                  public void windowClosing(java.awt.event.WindowEvent evt) {
                      exitForm(evt);
                  }
              });

              jButtonRefresh.setText("Refresh");
              jButtonRefresh.addActionListener(new java.awt.event.ActionListener() {
                  public void actionPerformed(java.awt.event.ActionEvent evt) {
                      jButtonRefreshActionPerformed(evt);
                  }
              });

              jPanelTop.add(jButtonRefresh);

              getContentPane().add(jPanelTop, java.awt.BorderLayout.NORTH);

              jTable1.setModel(getTableModel());
              jScrollPane1.setViewportView(jTable1);

              getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);

              pack();
          }

          private void jButtonRefreshActionPerformed(java.awt.event.ActionEvent evt) {
              refresh();
          }

          private void exitForm(java.awt.event.WindowEvent evt) {
              System.exit(0);
          }

          
          private TableModel getTableModel(){
              // Create a model of the data.
              TableModel dataModel = new AbstractTableModel() {
                  // These methods always need to be implemented.
                  public int getColumnCount() { return columnCount; }
                  public final int getRowCount() { return dataArray.length;}
                  public Object getValueAt(int row, int col) {
                      switch(col){
                          case 0:{
                              return dataArray[row];
                          }
                          case 1:{
                              return renderButton;
                          }
                      }// switch
                      return null;
                  }// method

                  public Class getColumnClass(int col) {return getValueAt(0,col).getClass();}
                  // The row containing the buttons must be editable
                  public boolean isCellEditable(int row, int col) {return (col==1);}
               };
               return dataModel;
          }// method
          
          

          private void refresh(){
              // Toggle between 2 sets of data
              if(dataArray == dataArray1){
                  dataArray = dataArray2;
              }// if
              else{
                  dataArray = dataArray1;
              }// else
              ((AbstractTableModel)this.jTable1.getModel()).fireTableDataChanged();
              // Clear any previous selection that would be meaningless with new data.
              this.jTable1.clearSelection();
          }// method
          
          private javax.swing.JButton jButtonRefresh;
          private javax.swing.JPanel jPanelTop;
          private javax.swing.JScrollPane jScrollPane1;
          private javax.swing.JTable jTable1;

      }// class


      public class ButtonCellEditor extends AbstractCellEditor implements TableCellEditor{
          
          private JButton sharedButton;

          public ButtonCellEditor(JButton sharedButton){
              this.sharedButton=sharedButton;
          }// constr

          // implementing TableCellEditor
          public Component getTableCellEditorComponent(
                  JTable table,
                  Object value,
                  boolean isSelected,
                  int row,
                  int column){
              return sharedButton;
          }// method

          // implementing CellEditor
          public Object getCellEditorValue(){
              return sharedButton;
          }// method

      }// class
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Please refer to the source code. It contains a flag "workaround"
      (Review ID: 183298)
      ======================================================================

            shickeysunw Shannon Hickey (Inactive)
            jkimsunw Jeffrey Kim (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: