Java tutorial
import java.awt.BorderLayout; import java.awt.Component; import java.awt.Container; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.text.NumberFormat; import java.util.Calendar; import java.util.EventObject; import java.util.GregorianCalendar; import java.util.Iterator; import java.util.StringTokenizer; import java.util.TreeSet; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.EventListenerList; import javax.swing.plaf.basic.BasicArrowButton; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; import javax.swing.table.TableModel; class SortedTableModel extends AbstractTableModel { protected TableModel sourceModel; protected int[] indexValues; public SortedTableModel(TableModel model) { super(); sourceModel = model; } public int getRowCount() { return sourceModel.getRowCount(); } public int getColumnCount() { return sourceModel.getColumnCount(); } public Object getValueAt(int row, int column) { if (indexValues != null) { row = getSourceIndex(row); } return sourceModel.getValueAt(row, column); } public void setValueAt(Object value, int row, int column) { if (indexValues != null) { row = getSourceIndex(row); } sourceModel.setValueAt(value, row, column); } public boolean isCellEditable(int row, int column) { return sourceModel.isCellEditable(row, column); } public String getColumnName(int column) { return sourceModel.getColumnName(column); } public Class getColumnClass(int column) { return sourceModel.getColumnClass(column); } public int getSourceIndex(int index) { if (indexValues != null) { return indexValues[index]; } return -1; } public void sortRows(int column, boolean ascending) { fireTableDataChanged(); } public void clearSort() { indexValues = null; fireTableDataChanged(); } } class SortedColumnHeaderRenderer implements TableCellRenderer { protected TableCellRenderer textRenderer; protected SortedTableModel sortedModel; protected int sortColumn = -1; protected boolean sortAscending = true; public SortedColumnHeaderRenderer(SortedTableModel model, TableCellRenderer renderer) { sortedModel = model; textRenderer = renderer; } public SortedColumnHeaderRenderer(SortedTableModel model) { this(model, null); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component text; JPanel panel = new JPanel(); panel.setLayout(new BorderLayout()); if (textRenderer != null) { text = textRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } else { text = new JLabel((String) value, JLabel.CENTER); LookAndFeel.installColorsAndFont((JComponent) text, "TableHeader.background", "TableHeader.foreground", "TableHeader.font"); } panel.add(text, BorderLayout.CENTER); if (column == sortColumn) { BasicArrowButton bab = new BasicArrowButton( (sortAscending ? SwingConstants.NORTH : SwingConstants.SOUTH)); panel.add(bab, BorderLayout.WEST); } LookAndFeel.installBorder(panel, "TableHeader.cellBorder"); return panel; } public void columnSelected(int column) { if (column != sortColumn) { sortColumn = column; sortAscending = true; } else { sortAscending = !sortAscending; if (sortAscending) sortColumn = -1; } if (sortColumn != -1) { sortedModel.sortRows(sortColumn, sortAscending); } else { sortedModel.clearSort(); } } } class TableValues extends AbstractTableModel { public final static int FIRST_NAME = 0; public final static int LAST_NAME = 1; public final static int DATE_OF_BIRTH = 2; public final static int ACCOUNT_BALANCE = 3; public final static int GENDER = 4; public final static boolean GENDER_MALE = true; public final static boolean GENDER_FEMALE = false; public final static String[] columnNames = { "First\nName", "Last\nName", "Date of\nBirth", "Account\nBalance", "Gender" }; public Object[][] values = { { "A", "B", new GregorianCalendar(1962, Calendar.FEBRUARY, 20).getTime(), new Float(12345.67), new Boolean(GENDER_MALE) }, { "C", "D", new GregorianCalendar(1987, Calendar.JANUARY, 6).getTime(), new Float(23456.78), new Boolean(GENDER_MALE) }, { "E", "F", new GregorianCalendar(1989, Calendar.AUGUST, 31).getTime(), new Float(34567.89), new Boolean(GENDER_FEMALE) }, { "G", "H", new GregorianCalendar(1945, Calendar.JANUARY, 16).getTime(), new Float(-456.70), new Boolean(GENDER_FEMALE) }, { "I", "J", new GregorianCalendar(1907, Calendar.AUGUST, 2).getTime(), new Float(567.00), new Boolean(GENDER_FEMALE) } }; public int getRowCount() { return values.length; } public int getColumnCount() { return values[0].length; } public Object getValueAt(int row, int column) { return values[row][column]; } public String getColumnName(int column) { return columnNames[column]; } public Class getColumnClass(int column) { Class dataType = super.getColumnClass(column); if (column == ACCOUNT_BALANCE) { dataType = Float.class; } else if (column == DATE_OF_BIRTH) { dataType = java.util.Date.class; } else if ((column == FIRST_NAME) || (column == LAST_NAME)) { dataType = String.class; } else if (column == GENDER) { dataType = Boolean.class; } return dataType; } public boolean isCellEditable(int row, int column) { if (column == GENDER) { return true; } return false; } public void setValueAt(Object value, int row, int column) { values[row][column] = value; } } public class SimpleTableTestMultilineHeader extends JFrame { protected JTable table; protected SortedColumnHeaderRenderer renderer; public static void main(String[] args) { SimpleTableTestMultilineHeader stt = new SimpleTableTestMultilineHeader(); stt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); stt.setSize(400, 200); stt.setVisible(true); } public SimpleTableTestMultilineHeader() { Container pane = getContentPane(); pane.setLayout(new BorderLayout()); TableValues tv = new TableValues(); SortedTableModel stm = new SortedTableModel(tv); stm.sortRows(TableValues.ACCOUNT_BALANCE, true); table = new JTable(stm); table.setRowSelectionAllowed(false); table.setColumnSelectionAllowed(true); TableColumnModel tcm = table.getColumnModel(); TableColumn tc = tcm.getColumn(TableValues.GENDER); MultiLineHeaderRenderer mlhr = new MultiLineHeaderRenderer(); tc = tcm.getColumn(TableValues.ACCOUNT_BALANCE); tc.setHeaderRenderer(mlhr); renderer = new SortedColumnHeaderRenderer(stm, mlhr); int count = tcm.getColumnCount(); for (int i = 0; i < count; i++) { tc = tcm.getColumn(i); tc.setHeaderRenderer(renderer); } JTableHeaderToolTips jthtt = new JTableHeaderToolTips(table.getColumnModel()); jthtt.setToolTips(new String[] { "Customer's First Name", "Customer's Last Name", "Customer's Date of Birth", "Customer's Account Balance", "Customer's Gender" }); table.setTableHeader(jthtt); JScrollPane jsp = new JScrollPane(table); pane.add(jsp, BorderLayout.CENTER); addHeaderListener(); } public void addHeaderListener() { table.getTableHeader().addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent event) { JTableHeader header = (JTableHeader) (event.getSource()); int index = header.columnAtPoint(event.getPoint()); Class dataType = table.getModel().getColumnClass(index); Class[] interfaces = dataType.getInterfaces(); for (int i = 0; i < interfaces.length; i++) { if (interfaces[i].equals(java.lang.Comparable.class)) { renderer.columnSelected(index); break; } } table.setColumnSelectionInterval(index, index); } }); } } class JTableHeaderToolTips extends JTableHeader { protected String[] toolTips; public JTableHeaderToolTips(TableColumnModel tcm) { super(tcm); } public void setToolTips(String[] tips) { toolTips = tips; } public String getToolTipText(MouseEvent event) { String tip = super.getToolTipText(event); int column = columnAtPoint(event.getPoint()); if ((toolTips != null) && (column < toolTips.length) && (toolTips[column] != null)) { tip = toolTips[column]; } return tip; } } class MultiLineHeaderRenderer extends JPanel implements TableCellRenderer { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JLabel label; removeAll(); String[] header = ((String) value).split("\n"); setLayout(new GridLayout(header.length, 1)); for (String s : header) { label = new JLabel(s, JLabel.CENTER); LookAndFeel.installColorsAndFont(label, "TableHeader.background", "TableHeader.foreground", "TableHeader.font"); add(label); } LookAndFeel.installBorder(this, "TableHeader.cellBorder"); return this; } }