List UI Properties in a JTable and sortable : Table « Swing JFC « Java

List UI Properties in a JTable and sortable

List UI Properties in a JTable and sortable
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski     
ISBN: 1-893115-78-X
Publisher: APress

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class ListProperties {
  static class CustomTableModel extends AbstractTableModel {
    Vector keys = new Vector();

    Vector values = new Vector();

    private static final String columnNames[] = { "Property String",
        "Value" };

    public int getColumnCount() {
      return columnNames.length;

    public String getColumnName(int column) {
      return columnNames[column];

    public int getRowCount() {
      return keys.size();

    public Object getValueAt(int row, int column) {
      Object returnValue = null;
      if (column == 0) {
        returnValue = keys.elementAt(row);
      } else if (column == 1) {
        returnValue = values.elementAt(row);

      return returnValue;

    public synchronized void uiDefaultsUpdate(UIDefaults defaults) {
      Enumeration newKeys = defaults.keys();
      while (newKeys.hasMoreElements()) {

      Enumeration newValues = defaults.elements();
      while (newValues.hasMoreElements()) {


  public static void main(String args[]) {
    final JFrame frame = new JFrame("List Properties");

    final CustomTableModel model = new CustomTableModel();
    TableSorter sorter = new TableSorter(model);

    JTable table = new JTable(sorter);
    TableHeaderSorter.install(sorter, table);


    UIManager.LookAndFeelInfo looks[] = UIManager

    ActionListener actionListener = new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
        final String lafClassName = actionEvent.getActionCommand();
        Runnable runnable = new Runnable() {
          public void run() {
            try {
              // Added
            } catch (Exception exception) {
                  "Can't change look and feel",
                  "Invalid PLAF", JOptionPane.ERROR_MESSAGE);

    JToolBar toolbar = new JToolBar();
    for (int i = 0, n = looks.length; i < n; i++) {
      JButton button = new JButton(looks[i].getName());

    Container content = frame.getContentPane();
    content.add(toolbar, BorderLayout.NORTH);
    JScrollPane scrollPane = new JScrollPane(table);
    content.add(scrollPane, BorderLayout.CENTER);
    frame.setSize(400, 400);

class TableSorter extends TableMap implements TableModelListener {
  int indexes[] = new int[0];

  Vector sortingColumns = new Vector();

  boolean ascending = true;

  public TableSorter() {

  public TableSorter(TableModel model) {

  public void setModel(TableModel model) {

  public int compareRowsByColumn(int row1, int row2, int column) {
    Class type = model.getColumnClass(column);
    TableModel data = model;

    // Check for nulls

    Object o1 = data.getValueAt(row1, column);
    Object o2 = data.getValueAt(row2, column);

    // If both values are null return 0
    if (o1 == null && o2 == null) {
      return 0;
    } else if (o1 == null) { // Define null less than everything.
      return -1;
    } else if (o2 == null) {
      return 1;

    if (type.getSuperclass() == Number.class) {
      Number n1 = (Number) data.getValueAt(row1, column);
      double d1 = n1.doubleValue();
      Number n2 = (Number) data.getValueAt(row2, column);
      double d2 = n2.doubleValue();

      if (d1 < d2)
        return -1;
      else if (d1 > d2)
        return 1;
        return 0;
    } else if (type == String.class) {
      String s1 = (String) data.getValueAt(row1, column);
      String s2 = (String) data.getValueAt(row2, column);
      int result = s1.compareTo(s2);

      if (result < 0)
        return -1;
      else if (result > 0)
        return 1;
        return 0;
    } else if (type == java.util.Date.class) {
      Date d1 = (Date) data.getValueAt(row1, column);
      long n1 = d1.getTime();
      Date d2 = (Date) data.getValueAt(row2, column);
      long n2 = d2.getTime();

      if (n1 < n2)
        return -1;
      else if (n1 > n2)
        return 1;
        return 0;
    } else if (type == Boolean.class) {
      Boolean bool1 = (Boolean) data.getValueAt(row1, column);
      boolean b1 = bool1.booleanValue();
      Boolean bool2 = (Boolean) data.getValueAt(row2, column);
      boolean b2 = bool2.booleanValue();

      if (b1 == b2)
        return 0;
      else if (b1) // Define false < true
        return 1;
        return -1;
    } else {
      Object v1 = data.getValueAt(row1, column);
      String s1 = v1.toString();
      Object v2 = data.getValueAt(row2, column);
      String s2 = v2.toString();
      int result = s1.compareTo(s2);

      if (result < 0)
        return -1;
      else if (result > 0)
        return 1;
        return 0;

  public int compare(int row1, int row2) {
    for (int level = 0, n = sortingColumns.size(); level < n; level++) {
      Integer column = (Integer) sortingColumns.elementAt(level);
      int result = compareRowsByColumn(row1, row2, column.intValue());
      if (result != 0) {
        return (ascending ? result : -result);
    return 0;

  public void reallocateIndexes() {
    int rowCount = model.getRowCount();
    indexes = new int[rowCount];
    for (int row = 0; row < rowCount; row++) {
      indexes[row] = row;

  public void tableChanged(TableModelEvent tableModelEvent) {

  public void checkModel() {
    if (indexes.length != model.getRowCount()) {
      System.err.println("Sorter not informed of a change in model.");

  public void sort() {
    shuttlesort((int[]) indexes.clone(), indexes, 0, indexes.length);

  public void shuttlesort(int from[], int to[], int low, int high) {
    if (high - low < 2) {
    int middle = (low + high) / 2;
    shuttlesort(to, from, low, middle);
    shuttlesort(to, from, middle, high);

    int p = low;
    int q = middle;

    for (int i = low; i < high; i++) {
      if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
        to[i] = from[p++];
      } else {
        to[i] = from[q++];

  private void swap(int first, int second) {
    int temp = indexes[first];
    indexes[first] = indexes[second];
    indexes[second] = temp;

  public Object getValueAt(int row, int column) {
    return model.getValueAt(indexes[row], column);

  public void setValueAt(Object aValue, int row, int column) {
    model.setValueAt(aValue, indexes[row], column);

  public void sortByColumn(int column) {
    sortByColumn(column, true);

  public void sortByColumn(int column, boolean ascending) {
    this.ascending = ascending;
    sortingColumns.addElement(new Integer(column));
    super.tableChanged(new TableModelEvent(this));

class TableHeaderSorter extends MouseAdapter {

  private TableSorter sorter;

  private JTable table;

  private TableHeaderSorter() {

  public static void install(TableSorter sorter, JTable table) {
    TableHeaderSorter tableHeaderSorter = new TableHeaderSorter();
    tableHeaderSorter.sorter = sorter;
    tableHeaderSorter.table = table;
    JTableHeader tableHeader = table.getTableHeader();

  public void mouseClicked(MouseEvent mouseEvent) {
    TableColumnModel columnModel = table.getColumnModel();
    int viewColumn = columnModel.getColumnIndexAtX(mouseEvent.getX());
    int column = table.convertColumnIndexToModel(viewColumn);
    if (mouseEvent.getClickCount() == 1 && column != -1) {
      System.out.println("Sorting ...");
      int shiftPressed = (mouseEvent.getModifiers() & InputEvent.SHIFT_MASK);
      boolean ascending = (shiftPressed == 0);
      sorter.sortByColumn(column, ascending);

class TableMap extends AbstractTableModel implements TableModelListener {

  TableModel model;

  public TableModel getModel() {
    return model;

  public void setModel(TableModel model) {
    if (this.model != null) {
    this.model = model;
    if (this.model != null) {

  public Class getColumnClass(int column) {
    return model.getColumnClass(column);

  public int getColumnCount() {
    return ((model == null) ? 0 : model.getColumnCount());

  public String getColumnName(int column) {
    return model.getColumnName(column);

  public int getRowCount() {
    return ((model == null) ? 0 : model.getRowCount());

  public Object getValueAt(int row, int column) {
    return model.getValueAt(row, column);

  public void setValueAt(Object value, int row, int column) {
    model.setValueAt(value, row, column);

  public boolean isCellEditable(int row, int column) {
    return model.isCellEditable(row, column);

  public void tableChanged(TableModelEvent tableModelEvent) {


Related examples in the same category

1.Creating a JTable Component
2.Creates tables that allow rows and columns to be added or deleted
3.Build a table from list data and column names
4.Getting the Number of Rows and Columns in a JTable Component
5.Appending a Row to a JTable Component
6.Add columns to a table through DefaultTableModel
7.Insert a row to a table through DefaultTableModel
8.Insert a row to a table through DefaultTableModel at specified row
9.Scroll Table SampleScroll Table Sample
10.Simple demonstration of JTableSimple demonstration of JTable
11.Create a table with two dimensional arrayCreate a table with two dimensional array
12.Create table with Unicode dataCreate table with Unicode data
13.Resize TableResize Table
14.Expense TableExpense Table
15.StockTable 6: Action and Dynamic DisplayStockTable 6: Action and Dynamic Display
16.JTable selection eventsJTable selection events
17.A table with the ability to play with row and column selectionsA table with the ability to play with row and column selections
18.Table Selection modeTable Selection mode
19.Display ResultSet in Table (JTable)
20.JTable(Table) with JDBC and ResultSetJTable(Table) with JDBC and ResultSet
21.Property Table: Use JTable to display and edit propertiesProperty Table: Use JTable to display and edit properties
22.Table with tool tips for both cells and column headersTable with tool tips for both cells and column headers
23.StockTable 4: Table SorterStockTable 4: Table Sorter
24.JTable sorter:click the table header to sort a column and a tableJTable sorter:click the table header to sort a column and a table
25.Creating image out of a JTable
28.JTable.setColumnSelectionAllowed(boolean b);
29.JTable.setRowSelectionAllowed(boolean b);
30.JTable.setCellSelectionEnabled(boolean b);
31.Handle selection and model change events for a JTable.
32.ListSelectionModel rowSelMod = JTable.getSelectionModel();
33.ListSelectionModel colSelMod = JTable.getColumnModel().getSelectionModel();
34.JTree.getModel().addTreeModelListener(new TreeModelListener())
35.Move the last visible column so it becomes the first visible column
36.the last column is moved to the first position
37.Allowing the User to Resize a Column in a JTable Component
38.Retrieve the value in the visible cell (1,2) in a JTable
39.Retrieve the value in cell (1,2) from the model
40.Change a cell in the 2nd visible column
41.Change a cell in the 3rd column in the model
42.Showing the Table Header in a Non-Scrollable JTable Component
43.Changing the Name of a Column in a JTable Component
44.Displaying an Icon in a Column Head of a JTable Component
45.Implementing Variable-Height Column Headers in a JTable Component
46.Removing the Column Headers from a Scrollable in a JTable Component
47.Creating a Custom Column Header Renderer in a JTable Component
48.Setting Column Header Tool Tips in a JTable Components
49.Setting Tool Tips on Cells in a JTable Component
50.Enable row selection (default) in a JTable
51.Enable column selection in a JTable
52.Enable cell selection in a JTable
53.Get default selection mode:MULTIPLE_INTERVAL_SELECTION
54.Allow only single a selection
55.Allow selection to span one contiguous set of rows, visible columns, or block of cells
56.Allow multiple selections of rows, visible columns, or cell blocks (default)
57.Select a column - column 0 in a JTable
58.Select an additional range of columns - columns 1 to 2
59.Deselect a range of columns - columns 0 to 1
60.Select a row - row 0
61.Select an additional range of rows - rows 1 to 2
62.Deselect a range of rows - rows 0 to 1
63.Select a cell: cell (2,1)
64.Extend the selection to include all cells (5,3)
65.Deselect a cell: cell (3,2), All cells in the row and column containing (3,2) are deselected.
66.Toggles the selection state, if it were called again, it exactly reverses the first call.
67.Select all cells
68.Deselect all cells
69.Column selection is enabled, get the indices of the selected columns
70.Row selection is enabled, Get the indices of the selected rows
71.Get selected row and selected index
72.Get the min and max ranges of selected cells
73.Check each cell in the min and max ranges of selected cells
74.Disabling Selections in a JTable Component
75.Getting the Anchor Cell in a JTable Component
76.Creating a Scrollable JTable Component
77.Disable auto resizing to make the table horizontal scrollable
78.Determining If a Cell Is Visible in a JTable Component
79.Making a Cell Visible in a JTable Component
80.Scrolling a Cell to the Center of a JTable Component
81.Show both horizontal and vertical grid lines (the default)
82.Don't show any grid lines
83.Show only vertical grid lines
84.Show only horizontal grid lines
85.Set the grid color
86.Getting the Gap Size Between Cells in a JTable Component
87.Add 5 spaces to the left and right sides of a cell.
88.Increase the row height
89.Programmatically Starting Cell Editing in a JTable Component
90.Save the current value in the cell being edited and stops the editing process
91.Discard any changes made by the user and stops the editing process
92.Disabling User Edits in a JTable
93.Disabling User Edits in a JTable with DefaultTableModel
94.Sorting the Rows in a JTable Component Based on a Column
95.Sorting a Column in a JTable Component
96.Listening for Selection Events in a JTable Component
97.Listening for Changes to the Rows and Columns of a JTable Component
98.Listening for Column-Related Changes in a JTable Component
99.Listening for Clicks on a Column Header in a JTable Component
100.Sorting and Filtering Tables
101.Use a regexFilter to filter table content
102.Creating a JTable with rows of variable height
103.Scroll JTable To Center