|
Java™ by example!
|
|
|
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!
|
|
|
|
|