title: Live sorting of JTable
body: <p>I've figured out how to get a <code>JTable</code> to be sorted properly, but I can't figure out how to get it to automatically update the sort order when a table cell is changed.  Right now, I have this (admittedly long) code, mostly based on that in the Java Tutorial's <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/table.html" rel="noreferrer">How to Use Tables</a>. I've highlighted the changes I've made with <code>// ADDED</code>. In this case, newly-added values sort properly, but when I go in to edit a value, it doesn't seem to resort, even though I call <code>fireTableCellUpdated</code>?</p>
  
  <p>In short, how can I get a table to re-sort when a data value changes in the model?</p>
  
  <pre><code>/*
   * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
   * See the standard BSD license.
   */ 
  
  package components;
  
  /*
   * TableSortDemo.java requires no other files.
   */
  
  import java.awt.Dimension;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.util.ArrayList;
  
  import javax.swing.BoxLayout;
  import javax.swing.JButton;
  import javax.swing.JFrame;
  import javax.swing.JOptionPane;
  import javax.swing.JPanel;
  import javax.swing.JScrollPane;
  import javax.swing.JTable;
  import javax.swing.table.AbstractTableModel;
  
  public class TableSortDemo extends JPanel {
      private boolean DEBUG = false;
  
      public TableSortDemo() {
          super();
          setLayout(new BoxLayout(TableSortDemo.this, BoxLayout.PAGE_AXIS));
          final MyTableModel m = new MyTableModel();
          JTable table = new JTable(m);
          table.setPreferredScrollableViewportSize(new Dimension(500, 70));
          table.setFillsViewportHeight(true);
          table.setAutoCreateRowSorter(true);
  
          //Create the scroll pane and add the table to it.
          JScrollPane scrollPane = new JScrollPane(table);
  
          //Add the scroll pane to this panel.
          add(scrollPane);
  
          // ADDED: button to add a value
          JButton addButton = new JButton("Add a new value");
          addButton.addActionListener(new ActionListener() {
              public void actionPerformed(ActionEvent e) {
                  m.addValue(
                          JOptionPane.showInputDialog(
                                  TableSortDemo.this, "Value?"));
              }
          });
  
          // ADDED button to change a value
          JButton setButton = new JButton("Change a value");
          setButton.addActionListener(new ActionListener() {
              /* (non-Javadoc)
               * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
               */
              public void actionPerformed(ActionEvent e) {
                  m.setValueAt(
                          JOptionPane.showInputDialog(
                                  TableSortDemo.this, "Value?"),
                          Integer.parseInt(
                                  JOptionPane.showInputDialog(
                                          TableSortDemo.this, "Which?")), 0);
              }
          });
          add(addButton);
          add(setButton);
      }
  
      class MyTableModel extends AbstractTableModel {
          private static final long serialVersionUID = -7053335255134714625L;
          private String[] columnNames = {"Column"};
          // ADDED data as mutable ArrayList
          private ArrayList&lt;String&gt; data = new ArrayList&lt;String&gt;();
  
          public MyTableModel() {
              data.add("Anders");
              data.add("Lars");
              data.add("Betty");
              data.add("Anna");
              data.add("Jon");
              data.add("Zach");
          }
  
          // ADDED
          public void addValue(Object v) {
              data.add(v.toString());
              int row = data.size() - 1;
              fireTableRowsInserted(row, row);
          }
  
          public int getColumnCount() {
              return columnNames.length;
          }
  
          public int getRowCount() {
              return data.size();
          }
  
          public String getColumnName(int col) {
              return columnNames[col];
          }
  
          public Object getValueAt(int row, int col) {
              return data.get(row) + " " + row;
          }
  
          /*
           * JTable uses this method to determine the default renderer/
           * editor for each cell.  If we didn't implement this method,
           * then the last column would contain text ("true"/"false"),
           * rather than a check box.
           */
          public Class&lt;String&gt; getColumnClass(int c) {
              return String.class;
          }
  
          /*
           * Don't need to implement this method unless your table's
           * editable.
           */
          public boolean isCellEditable(int row, int col) {
              //Note that the data/cell address is constant,
              //no matter where the cell appears onscreen.
              if (col &lt; 2) {
                  return false;
              } else {
                  return true;
              }
          }
  
          /*
           * Don't need to implement this method unless your table's
           * data can change.
           */
          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.set(row, value.toString());
  
              // ADDED: uncommented this line, despite warnings to the contrary
              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 &lt; numRows; i++) {
                  System.out.print("    row " + i + ":");
                  for (int j=0; j &lt; numCols; j++) {
                      System.out.print("  " + data.get(i));
                  }
                  System.out.println();
              }
              System.out.println("--------------------------");
          }
      }
  
      /**
       * Create the GUI and show it.  For thread safety,
       * this method should be invoked from the
       * event-dispatching thread.
       */
      private static void createAndShowGUI() {
          //Create and set up the window.
          JFrame frame = new JFrame("TableSortDemo");
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
          //Create and set up the content pane.
          TableSortDemo newContentPane = new TableSortDemo();
          newContentPane.setOpaque(true); //content panes must be opaque
          frame.setContentPane(newContentPane);
  
          //Display the window.
          frame.pack();
          frame.setVisible(true);
      }
  
      public static void main(String[] args) {
          //Schedule a job for the event-dispatching thread:
          //creating and showing this application's GUI.
          javax.swing.SwingUtilities.invokeLater(new Runnable() {
              public void run() {
                  createAndShowGUI();
              }
          });
      }
  }
  </code></pre>