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

Sortkeys vs Comparator Order Conflict in TableRowSorter

XMLWordPrintable

      FULL PRODUCT VERSION :
      java version "1.6.0_19"
      Java(TM) SE Runtime Environment (build 1.6.0_19-b04)
      Java HotSpot(TM) Client VM (build 16.2-b04, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Windows 7 32-bit

      A DESCRIPTION OF THE PROBLEM :
      When using TableRowSorter:
      if setComparator method is applied after the setSortKeys method, the TableRowSorter will ignore the Comparator. The Comparator should be applied regardless of the order that the two methods are applied.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      (1) write a custom comparator (e.g. sort strings based on string length)
      (2) Generate a table application with a custom TableModel. Generate a new instance of TableRowSorter. Generate a new instance of TableRowSorter, and a new ArrayList of type SortKey. Apply the setSortKeys method, then the setComparator method to the TableRowSorter.
      (3) Apply the TableRowSorter to the table application. The Comparator will not be applied.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The Comparator should be applied, regardless of the order of methods applied to TableRowSorter.
      ACTUAL -
      The TableRowSorter will ignore the Comparator if it is applied after the setSortKeys method.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      package com.dalefurrow.InvExTable;

      import javax.swing.JFrame;
      import javax.swing.JPanel;
      import javax.swing.JScrollPane;
      import javax.swing.JTable;
      import javax.swing.table.AbstractTableModel;
      import java.awt.*;
      import java.util.ArrayList;
      import java.util.Comparator;
      import javax.swing.RowSorter;
      import javax.swing.SortOrder;
      import javax.swing.table.TableModel;
      import javax.swing.table.TableRowSorter;

      /**
       * Example Code used to demonstrate bug in application or
       * TableRowSorter.setComparator()
       */
      public class TableSorterComparatorDemo extends JPanel {
          private boolean DEBUG = false;
          public JTable table;
          public TableModel model;

          public TableSorterComparatorDemo() {
              super(new GridLayout(1,0));

              model = new MyTableModel();
              table = new JTable(model); //ADDED THIS
              //JTable table = new JTable(new MyTableModel()); //OLD
              
      // table.applyComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); //must do this!

              Comparator<String> altComp = new Comparator<String>() {

              public int compare(String o1, String o2) {
                  Integer l1 = o1.length();
                  Integer l2 = o2.length();
                  return l1.compareTo(l2);
              }
          };
              TableRowSorter rowSorter = new TableRowSorter(model);
              rowSorter.setComparator(1, altComp);
              table.setRowSorter(rowSorter);
              table.setPreferredScrollableViewportSize(new Dimension(500, 200));
              //Create the scroll pane and add the table to it.
              JScrollPane scrollPane = new JScrollPane(table);

              //Add the scroll pane to this panel.
              add(scrollPane);
          }

          private void applySort() {
              Comparator<String> altComp = new Comparator<String>() {
                  public int compare(String o1, String o2) {
                      Integer l1 = o1.length();
                      Integer l2 = o2.length();
                      return l1.compareTo(l2);
                  }
              };
              TableRowSorter rowSorter = new TableRowSorter(model);
              ArrayList <RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
              sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));

              //BUG SECTION FOR TESTING
              rowSorter.setComparator(1, altComp); // must setComparator first in order to work!
              rowSorter.setSortKeys(sortKeys); //if the order is reversed, comparator will not be applied
             

              table.setRowSorter(rowSorter);

          }

          class MyTableModel extends AbstractTableModel {
              private String[] columnNames = {"First Name",
                                              "Last Name",
                                              "Sport",
                                              "# of Years",
                                              "Vegetarian"};
              private Object[][] data = {
                  {"Mary", "Campione",
                   "Snowboarding", new Integer(5), new Boolean(false)},
                  {"Alison", "Huml",
                   "Rowing", new Integer(3), new Boolean(true)},
                  {"Kathy", "Walrath",
                   "Knitting", new Integer(2), new Boolean(false)},
                  {"Sharon", "Zakhour",
                   "Speed reading", new Integer(20), new Boolean(true)},
                  {"Philip", "Milne",
                   "Pool", new Integer(10), new Boolean(false)},
                   {"Philip", "Parker",
                   "Rowing", new Integer(16), new Boolean(false)},
                   {"Carl", "Smith",
                   "Rowing", new Integer(4), new Boolean(true)},
                   {"Philip", "Allen",
                   "Rowing", new Integer(16), new Boolean(false)}

              };
              public int getColumnCount() {
                  return columnNames.length;
              }
              public int getRowCount() {
                  return data.length;
              }
              public String getColumnName(int col) {
                  return columnNames[col];
              }
              public Object getValueAt(int row, int col) {
                  return data[row][col];
              }
              
              public Class getColumnClass(int c) {
                  return getValueAt(0, c).getClass();
              }
              public boolean isCellEditable(int row, int col) {
                  if (col < 2) {
                      return false;
                  } else {
                      return true;
                  }
              }
              public void setValueAt(Object value, int row, int col) {
                  if (DEBUG) {
                      System.out.println("Setting value at " + row + "," + col
                                         + " to " + value
                                         + " (an instance of "
                                         + value.getClass() + ")");
                  }
                  data[row][col] = value;
                  fireTableCellUpdated(row, col);
                  if (DEBUG) {
                      System.out.println("New value of data:");
                      printDebugData();
                  }
              }

              private void printDebugData() {
                  int numRows = getRowCount();
                  int numCols = getColumnCount();

                  for (int i=0; i < numRows; i++) {
                      System.out.print(" row " + i + ":");
                      for (int j=0; j < numCols; j++) {
                          System.out.print(" " + data[i][j]);
                      }
                      System.out.println();
                  }
                  System.out.println("--------------------------");
              }
          }

         
          private static void createAndShowGUI() {

              //Create and set up the window.
              JFrame frame = new JFrame("TableSorterDemo");
              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              //Create and set up the content pane.
              TableSorterComparatorDemo newContentPane = new TableSorterComparatorDemo();
              newContentPane.setOpaque(true); //content panes must be opaque
              frame.setContentPane(newContentPane);
              //Display the window.
              frame.pack();
              frame.setVisible(true);
              //wait 5 seconds
              wait(5000);
              //apply Sort
              newContentPane.applySort();
          }

          public static void wait (int n){
              long t0,t1;
              t0=System.currentTimeMillis();
              do{
                  t1=System.currentTimeMillis();
              }
              while (t1-t0<1000);
      }

          public static void main(String[] args) {
              //Schedule a job for the event-dispatching thread:
              //creating and showing this application's GUI.
              createAndShowGUI();
          }
      }

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

      CUSTOMER SUBMITTED WORKAROUND :
      ensure setComparator is last method run on TableRowSorter before TableRowSorter is applied to JTable

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: