JDK-5105052 : Control-click draws wrong in JTable with column selection allowed
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.2
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-09-21
  • Updated: 2004-09-21
  • Resolved: 2004-09-21
Related Reports
Duplicate :  
Description

Name: gm110360			Date: 09/21/2004


FULL PRODUCT VERSION :
java version "1.4.2_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_04-b05)
Java HotSpot(TM) Client VM (build 1.4.2_04-b05, mixed mode)
and
java version "1.5.0-rc"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0-rc-b63)
Java HotSpot(TM) Client VM (build 1.5.0-rc-b63, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
Turning on ColumnSelection in a JTable will change the drawing behavior when
control-clicking on selected rows. The table will redraw as if no rows are
selected, when in fact the ListSelectionModel maintains the correct
selected indicies.


STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the test code. You will see two JTables. On each table, hold down the
control key and click on some unselected rows. Notice at the bottom of the table
it will show you all the rows that are currently selected. Then do a control-
click on a row that is already selected. You will see different behavior on
each table.
The only difference between the two tables is this: The first table has
column selection enabled, and the second one doesn't.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
All selected cells (or rows) should display with the selected background in
each table. (The selected rows for each table may be seen at the bottom of
the window.)

ACTUAL -
  In the first table, which has column selection enabled, clicking on a
cell that's already selected will redraw the column with nothing selected.
However, you can see from the bottom of the screen that everything that should be selected is still selected. In fact, at this point, if you click on an
unselected cell (in the same column), all the selected rows, including the
one you just clicked on, will redraw correctly.
  Interestingly, if your selection spans two columns, the control-click
will only draw one of the columns incorrectly. The column you didn't click
into will work.
  The second table behaves correctly because column selection is disabled.


REPRODUCIBILITY :
This bug can be reproduced always.

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

public class ControlClickBug
    extends JPanel
{
  private static JFrame mf;
  String[] data = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};

  public static void main(String[] args)
  {
    // comment out these two lines to see that the problem doesn't depend
    // on the look and feel.
    try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }
    catch (Exception err) { err.printStackTrace(); }
    mf=new JFrame("Control Click Bug");
    mf.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    ControlClickBug view=new ControlClickBug();
    mf.getContentPane().setLayout(new BorderLayout());
    mf.getContentPane().add(view, BorderLayout.CENTER);
    mf.setBounds(10, 10, 600, 400);
    mf.setVisible(true);
  }

  private ControlClickBug()
  {
    super(new GridLayout(1, 0));
    add(makeTable(true));
    add(makeTable(false));
  }
  
  private JPanel makeTable(boolean allowColumn)
  {
    JPanel pnl = new JPanel(new BorderLayout());
    TableModel mdl = new BugModel();
    JTable tbl = new JTable(mdl);
    if (allowColumn)
      tbl.setColumnSelectionAllowed(true);
    tbl.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    JScrollPane scr = new JScrollPane(tbl);
    pnl.add(scr, BorderLayout.CENTER);
    final JLabel lbl = new JLabel();
    pnl.add(lbl, BorderLayout.SOUTH);
    ListSelectionListener tblLsnr = new ListSelectionListener()
    {
      public void valueChanged(ListSelectionEvent e)
      {
        StringBuffer buf = new StringBuffer("Selected Items: ");
        ListSelectionModel mdl = (ListSelectionModel) e.getSource();
        for (int ii=mdl.getMinSelectionIndex(); ii<=mdl.getMaxSelectionIndex(); ++ii)
          if(mdl.isSelectedIndex(ii))
          {
            buf.append(data[ii].toString());
            buf.append(" ");
          }
        lbl.setText("<html><body>" + buf + "</body></html>");
      }
    };
    tbl.getSelectionModel().addListSelectionListener(tblLsnr);
    return pnl;
  }
  
  private class BugModel extends AbstractTableModel
  {
    public int getRowCount() { return data.length; }
    public int getColumnCount() { return 2; }
    public Object getValueAt(int rowIndex, int columnIndex)
    {
      if (columnIndex == 1)
        return data[rowIndex];
      return "" + rowIndex;
    }
  }
}

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

CUSTOMER SUBMITTED WORKAROUND :
Leave column selection off. (Not always feasable)
(Incident Review ID: 311108) 
======================================================================

Comments
EVALUATION When both column selection and row selection are enabled, JTable shows a cell as selected only if both its row and column are selected. That is, selection is simply the intersection of selected rows and columns. With the attached test case, here's what is happening: When the set of cells are first CTRL-clicked on, JTable marks them as selected by storing that the row and column for the clicked cells are selected. When CTRL-clicking again on the selected cell, this marks the row and column of that cell as being unselected. As a result, this unselects any other rows in the unselected column and any other columns in the unselected row. This is an unfortunate side effect of the way that JTable maintains selection. An existing RFE hopes to remedy this (4138111). ###@###.### 2004-09-21
21-09-2004