esuslogo
 [To advertise Java(tm) Events here, contact us!]
banner

Java™
by example!






New @ Esus.com


  gb  In-house search engine for better results!

  gb  Get updates with the esus.com
newsletter!









  Home 
 Browse Categories 
 Ask a Java Question 
 Help 
  For Java Tips & Tricks, subscribe to the esus.com newsletter!
Search Java Q&A, Links, API's:   adv 

How do I sort the rows in a JTable by clicking on a column header?

Courtesy of Nobuo Tamemasa (http://www2.gol.com/users/tame/swing/examples/JTableExamples5.html)





SortableTableExample.java:


import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import javax.swing.*;
import javax.swing.table.*;

/**
* @version 1.0 02/25/99
*/
public class SortableTableExample extends JPanel {

public SortableTableExample(){
setLayout(new BorderLayout());
String[] headerStr = {"Name","Date","Size","Dir"};
int[] columnWidth = {100,150,100,50};

SortableTableModel dm = new SortableTableModel() {
public Class getColumnClass(int col) {
switch (col) {
case 0: return String.class;
case 1: return Date.class;
case 2: return Integer.class;
case 3: return Boolean.class;
default: return Object.class;
}
}
public boolean isCellEditable(int row, int col) {
switch (col) {
case 1: return false;
default: return true;
}
}
public void setValueAt(Object obj, int row, int col) {
switch (col) {
case 2: super.setValueAt(new Integer(obj.toString()), row, col); return;
default: super.setValueAt(obj, row, col); return;
}
}
};
dm.setDataVector(new Object[][]{
{"b" ,getDate("98/12/02"),new Integer(14),new Boolean(false)},
{"a" ,getDate("99/01/01"),new Integer(67),new Boolean(false)},
{"d" ,getDate("99/02/11"),new Integer(2) ,new Boolean(false)},
{"c" ,getDate("99/02/27"),new Integer(7) ,new Boolean(false)},
{"foo" ,new Date() ,new Integer(5) ,new Boolean(true)},
{"bar" ,new Date() ,new Integer(10),new Boolean(true)}},
headerStr);

JTable table = new JTable(dm);
//table.setShowGrid(false);
table.setShowVerticalLines(true);
table.setShowHorizontalLines(false);
SortButtonRenderer renderer = new SortButtonRenderer();
TableColumnModel model = table.getColumnModel();
int n = headerStr.length;
for (int i=0;i<n;i++) {
model.getColumn(i).setHeaderRenderer(renderer);
model.getColumn(i).setPreferredWidth(columnWidth[i]);
}

JTableHeader header = table.getTableHeader();
header.addMouseListener(new HeaderListener(header,renderer));
JScrollPane pane = new JScrollPane(table);
add(pane, BorderLayout.CENTER);
}

public static void main(String[] args) {
JFrame f= new JFrame("SortableTable Example");
f.getContentPane().add(new SortableTableExample(), BorderLayout.CENTER);
f.setSize(400, 160);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
}

private static DateFormat dateFormat =
DateFormat.getDateInstance(DateFormat.SHORT, Locale.JAPAN);

private static Date getDate(String dateString) {
Date date = null;
try {
date = dateFormat.parse(dateString);
} catch(ParseException ex) {
date = new Date();
}
return date;
}

class HeaderListener extends MouseAdapter {
JTableHeader header;
SortButtonRenderer renderer;

HeaderListener(JTableHeader header,SortButtonRenderer renderer) {
this.header = header;
this.renderer = renderer;
}

public void mousePressed(MouseEvent e) {
int col = header.columnAtPoint(e.getPoint());
int sortCol = header.getTable().convertColumnIndexToModel(col);
renderer.setPressedColumn(col);
renderer.setSelectedColumn(col);
header.repaint();

if (header.getTable().isEditing()) {
header.getTable().getCellEditor().stopCellEditing();
}

boolean isAscent;
if (SortButtonRenderer.DOWN == renderer.getState(col)) {
isAscent = true;
} else {
isAscent = false;
}
((SortableTableModel)header.getTable().getModel())
.sortByColumn(sortCol, isAscent);
}

public void mouseReleased(MouseEvent e) {
int col = header.columnAtPoint(e.getPoint());
renderer.setPressedColumn(-1); // clear
header.repaint();
}
}
}



SortableTableModel.java:


import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

/**
* @version 1.0 02/25/99
*/
public class SortableTableModel extends DefaultTableModel {
int[] indexes;
TableSorter sorter;

public SortableTableModel() {
}

public Object getValueAt(int row, int col) {
int rowIndex = row;
if (indexes != null) {
rowIndex = indexes[row];
}
return super.getValueAt(rowIndex, col);
}

public void setValueAt(Object value, int row, int col) {
int rowIndex = row;
if (indexes != null) {
rowIndex = indexes[row];
}
super.setValueAt(value, rowIndex, col);
}


public void sortByColumn(int column, boolean isAscent) {
if (sorter == null) {
sorter = new TableSorter(this);
}
sorter.sort(column, isAscent);
fireTableDataChanged();
}

public int[] getIndexes() {
int n = getRowCount();
if (indexes != null) {
if (indexes.length == n) {
return indexes;
}
}
indexes = new int[n];
for (int i=0; i<n; i++) {
indexes[i] = i;
}
return indexes;
}
}



TableSorter.java:


import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

/**
* @version 1.0 02/25/99
*/
public class TableSorter {
SortableTableModel model;

public TableSorter(SortableTableModel model) {
this.model = model;
}


//n2 selection
public void sort(int column, boolean isAscent) {
int n = model.getRowCount();
int[] indexes = model.getIndexes();

for (int i=0; i<n-1; i++) {
int k = i;
for (int j=i+1; j<n; j++) {
if (isAscent) {
if (compare(column, j, k) < 0) {
k = j;
}
} else {
if (compare(column, j, k) > 0) {
k = j;
}
}
}
int tmp = indexes[i];
indexes[i] = indexes[k];
indexes[k] = tmp;
}
}


// comparaters

public int compare(int column, int row1, int row2) {
Object o1 = model.getValueAt(row1, column);
Object o2 = model.getValueAt(row2, column);
if (o1 == null && o2 == null) {
return 0;
} else if (o1 == null) {
return -1;
} else if (o2 == null) {
return 1;
} else {
Class type = model.getColumnClass(column);
if (type.getSuperclass() == Number.class) {
return compare((Number)o1, (Number)o2);
} else if (type == String.class) {
return ((String)o1).compareTo((String)o2);
} else if (type == Date.class) {
return compare((Date)o1, (Date)o2);
} else if (type == Boolean.class) {
return compare((Boolean)o1, (Boolean)o2);
} else {
return ((String)o1).compareTo((String)o2);
}
}
}

public int compare(Number o1, Number o2) {
double n1 = o1.doubleValue();
double n2 = o2.doubleValue();
if (n1 < n2) {
return -1;
} else if (n1 > n2) {
return 1;
} else {
return 0;
}
}

public int compare(Date o1, Date o2) {
long n1 = o1.getTime();
long n2 = o2.getTime();
if (n1 < n2) {
return -1;
} else if (n1 > n2) {
return 1;
} else {
return 0;
}
}

public int compare(Boolean o1, Boolean o2) {
boolean b1 = o1.booleanValue();
boolean b2 = o2.booleanValue();
if (b1 == b2) {
return 0;
} else if (b1) {
return 1;
} else {
return -1;
}
}
}



SortButtonRenderer.java:


import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

/**
* @version 1.0 02/25/99
*/
public class SortButtonRenderer extends JButton implements TableCellRenderer {
public static final int NONE = 0;
public static final int DOWN = 1;
public static final int UP = 2;

int pushedColumn;
Hashtable state;
JButton downButton,upButton;

public SortButtonRenderer() {
pushedColumn = -1;
state = new Hashtable();

setMargin(new Insets(0,0,0,0));
setHorizontalTextPosition(LEFT);
setIcon(new BlankIcon());

// perplexed
// ArrowIcon(SwingConstants.SOUTH, true)
// BevelArrowIcon (int direction, boolean isRaisedView, boolean isPressedView)

downButton = new JButton();
downButton.setMargin(new Insets(0,0,0,0));
downButton.setHorizontalTextPosition(LEFT);
downButton.setIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
downButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.DOWN, false, true));

upButton = new JButton();
upButton.setMargin(new Insets(0,0,0,0));
upButton.setHorizontalTextPosition(LEFT);
upButton.setIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, false));
upButton.setPressedIcon(new BevelArrowIcon(BevelArrowIcon.UP, false, true));

}

public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JButton button = this;
Object obj = state.get(new Integer(column));
if (obj != null) {
if (((Integer)obj).intValue() == DOWN) {
button = downButton;
} else {
button = upButton;
}
}
button.setText((value ==null) ? "" : value.toString());
boolean isPressed = (column == pushedColumn);
button.getModel().setPressed(isPressed);
button.getModel().setArmed(isPressed);
return button;
}

public void setPressedColumn(int col) {
pushedColumn = col;
}

public void setSelectedColumn(int col) {
if (col < 0) return;
Integer value = null;
Object obj = state.get(new Integer(col));
if (obj == null) {
value = new Integer(DOWN);
} else {
if (((Integer)obj).intValue() == DOWN) {
value = new Integer(UP);
} else {
value = new Integer(DOWN);
}
}
state.clear();
state.put(new Integer(col), value);
}

public int getState(int col) {
int retValue;
Object obj = state.get(new Integer(col));
if (obj == null) {
retValue = NONE;
} else {
if (((Integer)obj).intValue() == DOWN) {
retValue = DOWN;
} else {
retValue = UP;
}
}
return retValue;
}
}



BevelArrowIcon.java:


import java.awt.*;
import javax.swing.*;

/**
* @version 1.0 02/26/99
*/
public class BevelArrowIcon implements Icon {
public static final int UP = 0; // direction
public static final int DOWN = 1;

private static final int DEFAULT_SIZE = 11;

private Color edge1;
private Color edge2;
private Color fill;
private int size;
private int direction;

public BevelArrowIcon(int direction, boolean isRaisedView, boolean isPressedView) {
if (isRaisedView) {
if (isPressedView) {
init( UIManager.getColor("controlLtHighlight"),
UIManager.getColor("controlDkShadow"),
UIManager.getColor("controlShadow"),
DEFAULT_SIZE, direction);
} else {
init( UIManager.getColor("controlHighlight"),
UIManager.getColor("controlShadow"),
UIManager.getColor("control"),
DEFAULT_SIZE, direction);
}
} else {
if (isPressedView) {
init( UIManager.getColor("controlDkShadow"),
UIManager.getColor("controlLtHighlight"),
UIManager.getColor("controlShadow"),
DEFAULT_SIZE, direction);
} else {
init( UIManager.getColor("controlShadow"),
UIManager.getColor("controlHighlight"),
UIManager.getColor("control"),
DEFAULT_SIZE, direction);
}
}
}

public BevelArrowIcon(Color edge1, Color edge2, Color fill,
int size, int direction) {
init(edge1, edge2, fill, size, direction);
}

public void paintIcon(Component c, Graphics g, int x, int y) {
switch (direction) {
case DOWN: drawDownArrow(g, x, y); break;
case UP: drawUpArrow(g, x, y); break;
}
}

public int getIconWidth() {
return size;
}

public int getIconHeight() {
return size;
}


private void init(Color edge1, Color edge2, Color fill,
int size, int direction) {
this.edge1 = edge1;
this.edge2 = edge2;
this.fill = fill;
this.size = size;
this.direction = direction;
}

private void drawDownArrow(Graphics g, int xo, int yo) {
g.setColor(edge1);
g.drawLine(xo, yo, xo+size-1, yo);
g.drawLine(xo, yo+1, xo+size-3, yo+1);
g.setColor(edge2);
g.drawLine(xo+size-2, yo+1, xo+size-1, yo+1);
int x = xo+1;
int y = yo+2;
int dx = size-6;
while (y+1 < yo+size) {
g.setColor(edge1);
g.drawLine(x, y, x+1, y);
g.drawLine(x, y+1, x+1, y+1);
if (0 < dx) {
g.setColor(fill);
g.drawLine(x+2, y, x+1+dx, y);
g.drawLine(x+2, y+1, x+1+dx, y+1);
}
g.setColor(edge2);
g.drawLine(x+dx+2, y, x+dx+3, y);
g.drawLine(x+dx+2, y+1, x+dx+3, y+1);
x += 1;
y += 2;
dx -= 2;
}
g.setColor(edge1);
g.drawLine(xo+(size/2), yo+size-1, xo+(size/2), yo+size-1);
}

private void drawUpArrow(Graphics g, int xo, int yo) {
g.setColor(edge1);
int x = xo+(size/2);
g.drawLine(x, yo, x, yo);
x--;
int y = yo+1;
int dx = 0;
while (y+3 < yo+size) {
g.setColor(edge1);
g.drawLine(x, y, x+1, y);
g.drawLine(x, y+1, x+1, y+1);
if (0 < dx) {
g.setColor(fill);
g.drawLine(x+2, y, x+1+dx, y);
g.drawLine(x+2, y+1, x+1+dx, y+1);
}
g.setColor(edge2);
g.drawLine(x+dx+2, y, x+dx+3, y);
g.drawLine(x+dx+2, y+1, x+dx+3, y+1);
x -= 1;
y += 2;
dx += 2;
}
g.setColor(edge1);
g.drawLine(xo, yo+size-3, xo+1, yo+size-3);
g.setColor(edge2);
g.drawLine(xo+2, yo+size-2, xo+size-1, yo+size-2);
g.drawLine(xo, yo+size-1, xo+size, yo+size-1);
}
}



BlankIcon.java:


import java.awt. *;
import javax.swing. *;

/**
* @version 1.0 02/26/99
*/
public class BlankIcon implements Icon {
private Color fillColor;
private int size;

public BlankIcon() {
this(null, 11);
}

public BlankIcon(Color color, int size) {
//UIManager.getColor("control")
//UIManager.getColor("controlShadow")
fillColor = color;

this.size = size;
}

public void paintIcon(Component c, Graphics g, int x, int y) {
if (fillColor != null) {
g.setColor(fillColor);
g.drawRect(x, y, size-1, size-1);
}
}

public int getIconWidth() {
return size;
}

public int getIconHeight() {
return size;
}
}




Further Information
Author of answer:

Comments
Comments to this answer are only viewable by members. Login or become a member!





Terms of Service | Privacy Policy | Contact

Copyright © 2000-2003 Esus.com - All Rights Reserved 
Java and all Java-based trademarks are trademarks of Sun Microsystems, Inc. Esus.com is independent of Sun Microsystems, Inc. All other trademarks are the sole property of their respective owners.