Multiline table header
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;
}
}
Related examples in the same category