Java/Swing Components/Grid Table
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 Animated Icon Header Example
- 2 Animated Icon Table Example
- 3 Button Table Example
- 4 Calculated Column Table
- 5 Cell Border Table Example
- 6 Colored Cell Table Example
- 7 Column Border Table Example
- 8 Column popup menu
- 9 ComboBox Table
- 10 CurrencyTable
- 11 Each Row with different Editor Example
- 12 Editable Header Table Example
- 13 Editable Header Table Example 2
- 14 Editable Highlight Currency Table
- 15 Fixed Table Column Example
- 16 Fixed Table Row Example
- 17 Fraction Currency Table
- 18 Groupable(Group) Header Example
- 19 Hide Column Table Example
- 20 Highlight Currency Table
- 21 Highlight Currency Table 2
- 22 Icon Currency Table
- 23 Indicator Table Example
- 24 JSortTable
- 25 Mixed Table Example
- 26 MultiLine Cell Example
- 27 MultiLine Header Example
- 28 MultiLine Header Table
- 29 MultiLine Table
- 30 multiple Component Table 2: checkbox
- 31 Multiple Component Table: Checkbox and Combobox
- 32 multiple Font Cell Table Example
- 33 multiple Row Header Example
- 34 Multi Span Cell Table Example
- 35 MultiWidth Header Example
- 36 Pushable Table Header Example
- 37 Radio Button Table Example
- 38 RadioButton Table Example 2
- 39 Sortable Table Example
- 40 Striped Currency Table
- 41 Swing Table in ComboBox
- 42 Tabbable Currency Table
- 43 Table Row Header Example
- 44 Table Utilities
- 45 ToolTip Header Table Example
- 46 ToolTip Table
- 47 Total(Calculate) Row Example
- 48 Union Data Table Example
- 49 Updatable Highlight Currency Table
Animated Icon Header Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta2) */
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
/**
* @version 1.0 06/19/99
*/
public class AnimatedIconHeaderExample extends JFrame {
public AnimatedIconHeaderExample() {
super("AnimatedIconHeader Example");
final Object[][] data = new Object[][] { { "Leopard", "Lycaon" },
{ "Jagur", "Jackal" }, { "Cheetah", "Coyote" },
{ "Puma", "Dingo" }, { "Lynx", "Fox" }, { "Tom", "Hot" } };
final String[] column = new String[] { "Cat", "Dog" };
ImageIcon[] icons = { new ImageIcon("jexpAnimation.gif"),
new ImageIcon("jexpAnimation.gif") };
AbstractTableModel model = new AbstractTableModel() {
public int getColumnCount() {
return column.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return column[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
};
JTable table = new JTable(model);
JTableHeader header = table.getTableHeader();
JLabel renderer;
for (int i = 0; i < model.getColumnCount(); i++) {
renderer = (JLabel) table.getColumn(column[i]).getHeaderRenderer();
renderer.setIcon(icons[i]);
// If you have only one column.
// icons[i].setImageObserver(header);
icons[i].setImageObserver(new HeaderImageObserver(header, i));
}
JScrollPane pane = new JScrollPane(table);
getContentPane().add(pane);
}
class HeaderImageObserver implements ImageObserver {
JTableHeader header;
int col;
HeaderImageObserver(JTableHeader header, int col) {
this.header = header;
this.col = col;
}
public boolean imageUpdate(Image img, int flags, int x, int y, int w,
int h) {
if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
Rectangle rect = header.getHeaderRect(col);
header.repaint(rect);
}
return (flags & (ALLBITS | ABORT)) == 0;
}
}
public static void main(String[] args) {
AnimatedIconHeaderExample frame = new AnimatedIconHeaderExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(300, 140);
frame.setVisible(true);
}
}
Animated Icon Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta2) */
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
/**
* @version 1.0 06/19/99
*/
public class AnimatedIconTableExample extends JFrame {
public AnimatedIconTableExample() {
super("AnimatedIconTable Example");
final Object[][] data = new Object[][] {
{ new ImageIcon("jexpAnimation.gif"),
new ImageIcon("jexpAnimation.gif") },
{ new ImageIcon("jexpAnimation.gif"),
new ImageIcon("jexpAnimation.gif") } };
final Object[] column = new Object[] { "Boy and Girl", "Dog and Cat" };
AbstractTableModel model = new AbstractTableModel() {
public int getColumnCount() {
return column.length;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return (String) column[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public Class getColumnClass(int col) {
return ImageIcon.class;
}
};
JTable table = new JTable(model);
table.setRowHeight(50);
setImageObserver(table);
JScrollPane pane = new JScrollPane(table);
getContentPane().add(pane);
}
private void setImageObserver(JTable table) {
TableModel model = table.getModel();
int colCount = model.getColumnCount();
int rowCount = model.getRowCount();
for (int col = 0; col < colCount; col++) {
if (ImageIcon.class == model.getColumnClass(col)) {
for (int row = 0; row < rowCount; row++) {
ImageIcon icon = (ImageIcon) model.getValueAt(row, col);
if (icon != null) {
icon.setImageObserver(new CellImageObserver(table, row,
col));
}
}
}
}
}
class CellImageObserver implements ImageObserver {
JTable table;
int row;
int col;
CellImageObserver(JTable table, int row, int col) {
this.table = table;
this.row = row;
this.col = col;
}
public boolean imageUpdate(Image img, int flags, int x, int y, int w,
int h) {
if ((flags & (FRAMEBITS | ALLBITS)) != 0) {
Rectangle rect = table.getCellRect(row, col, false);
table.repaint(rect);
}
return (flags & (ALLBITS | ABORT)) == 0;
}
}
public static void main(String[] args) {
AnimatedIconTableExample frame = new AnimatedIconTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(300, 150);
frame.setVisible(true);
}
}
Button Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.ruponent;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
* @version 1.0 11/09/98
*/
public class JButtonTableExample extends JFrame {
public JButtonTableExample() {
super("JButtonTable Example");
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][] { { "button 1", "foo" },
{ "button 2", "bar" } }, new Object[] { "Button", "String" });
JTable table = new JTable(dm);
table.getColumn("Button").setCellRenderer(new ButtonRenderer());
table.getColumn("Button").setCellEditor(
new ButtonEditor(new JCheckBox()));
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
setSize(400, 100);
setVisible(true);
}
public static void main(String[] args) {
JButtonTableExample frame = new JButtonTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/**
* @version 1.0 11/09/98
*/
class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
}
setText((value == null) ? "" : value.toString());
return this;
}
}
/**
* @version 1.0 11/09/98
*/
class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private String label;
private boolean isPushed;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
return button;
}
public Object getCellEditorValue() {
if (isPushed) {
//
//
JOptionPane.showMessageDialog(button, label + ": Ouch!");
// System.out.println(label + ": Ouch!");
}
isPushed = false;
return new String(label);
}
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
Calculated Column Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.ruponent;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class CalculatedColumnTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Calculated Column Table");
JTable tbl = new JTable(new CurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
// Automatically configure the column widths
TableUtilities
.setColumnWidths(tbl, new Insets(0, 4, 0, 4), true, false);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
// Diagnostics: display the chosen column widths
for (int i = 0; i < tcm.getColumnCount(); i++) {
System.out.println("Column " + i + ": width is "
+ tcm.getColumn(i).getPreferredWidth());
}
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class TableUtilities {
// Calculate the required width of a table column
public static int calculateColumnWidth(JTable table, int columnIndex) {
int width = 0; // The return value
int rowCount = table.getRowCount();
for (int i = 0; i < rowCount; i++) {
TableCellRenderer renderer = table.getCellRenderer(i, columnIndex);
Component comp = renderer.getTableCellRendererComponent(table,
table.getValueAt(i, columnIndex), false, false, i,
columnIndex);
int thisWidth = comp.getPreferredSize().width;
if (thisWidth > width) {
width = thisWidth;
}
}
return width;
}
// Set the widths of every column in a table
public static void setColumnWidths(JTable table, Insets insets,
boolean setMinimum, boolean setMaximum) {
int columnCount = table.getColumnCount();
TableColumnModel tcm = table.getColumnModel();
int spare = (insets == null ? 0 : insets.left + insets.right);
for (int i = 0; i < columnCount; i++) {
int width = calculateColumnWidth(table, i);
width += spare;
TableColumn column = tcm.getColumn(i);
column.setPreferredWidth(width);
if (setMinimum == true) {
column.setMinWidth(width);
}
if (setMaximum == true) {
column.setMaxWidth(width);
}
}
}
// Sort an array of integers in place
public static void sort(int[] values) {
int length = values.length;
if (length > 1) {
for (int i = 0; i < length - 1; i++) {
for (int j = i + 1; j < length; j++) {
if (values[j] < values[i]) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
}
}
}
}
Cell Border Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
* @version 1.0 3/06/99
*/
public class CellBorderTableExample extends JFrame {
public CellBorderTableExample() {
super("Cell Border Example");
final Color color = UIManager.getColor("Table.gridColor");
DefaultTableModel dm = new DefaultTableModel(12, 6) {
public void setValueAt(Object obj, int row, int col) {
if (obj instanceof MyData) {
super.setValueAt(obj, row, col);
} else {
MyData myData = null;
Object oldObject = getValueAt(row, col);
if (oldObject == null) {
myData = new MyData(obj, new LinesBorder(color, 0));
} else if (oldObject instanceof MyData) {
myData = (MyData) oldObject;
} else {
System.out.println("error");
return;
}
myData.setObject(obj);
super.setValueAt(myData, row, col);
}
}
};
JTable table = new JTable(dm);
table.setIntercellSpacing(new Dimension(0, 0));
table.setCellSelectionEnabled(true);
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setDefaultRenderer(Object.class, new BorderCellRenderer());
JScrollPane scroll = new JScrollPane(table);
ThicknessPanel thicknessPanel = new ThicknessPanel();
Box box = new Box(BoxLayout.Y_AXIS);
box.add(thicknessPanel);
box.add(new ButtonPanel(table, thicknessPanel));
getContentPane().add(scroll, BorderLayout.CENTER);
getContentPane().add(box, BorderLayout.EAST);
}
public static void main(String[] args) {
CellBorderTableExample frame = new CellBorderTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(400, 240);
frame.setVisible(true);
}
class ThicknessPanel extends JPanel {
JComboBox[] combos;
ThicknessPanel() {
String[] str = { "top", "left", "bottom", "right" };
int n = str.length;
setLayout(new GridLayout(n, 2));
setBorder(new TitledBorder("Thickness"));
combos = new JComboBox[n];
for (int i = 0; i < n; i++) {
combos[i] = new JComboBox(new Object[] { "0", "1", "2", "3" });
add(new JLabel(str[i]));
add(combos[i]);
}
}
public Insets getThickness() {
Insets insets = new Insets(0, 0, 0, 0);
insets.top = combos[0].getSelectedIndex();
insets.left = combos[1].getSelectedIndex();
insets.bottom = combos[2].getSelectedIndex();
insets.right = combos[3].getSelectedIndex();
return insets;
}
}
class ButtonPanel extends JPanel {
JTable table;
ThicknessPanel thicknessPanel;
Color color = UIManager.getColor("Table.gridColor");
ButtonPanel(JTable table, ThicknessPanel thicknessPanel) {
this.table = table;
this.thicknessPanel = thicknessPanel;
setLayout(new GridLayout(3, 1));
setBorder(new TitledBorder("Append Lines"));
final JCheckBox oneBlock = new JCheckBox("Block");
JButton b_and = new JButton("REPLACE");
JButton b_or = new JButton("OR");
add(oneBlock);
add(b_and);
add(b_or);
b_and.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setCellBorder(true, oneBlock.isSelected());
}
});
b_or.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setCellBorder(false, oneBlock.isSelected());
}
});
}
private void setCellBorder(boolean isReplace, boolean isBlock) {
boolean isTop, isLeft, isBottom, isRight;
Insets insets = thicknessPanel.getThickness();
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
int rowMax = rows.length;
int columnMax = columns.length;
for (int i = 0; i < rowMax; i++) {
int row = rows[i];
isTop = (i == 0) ? true : false;
isBottom = (i == rowMax - 1) ? true : false;
for (int j = 0; j < columnMax; j++) {
int column = columns[j];
isLeft = (j == 0) ? true : false;
isRight = (j == columnMax - 1) ? true : false;
MyData myData = (MyData) table.getValueAt(row, column);
if (myData == null) {
myData = new MyData("", new LinesBorder(color, 0));
}
LinesBorder border = (LinesBorder) myData.getBorder();
if (isBlock) {
Insets tmp = new Insets(0, 0, 0, 0);
if (isTop)
tmp.top = Math.max(tmp.top, insets.top);
if (isLeft)
tmp.left = Math.max(tmp.left, insets.left);
if (isBottom)
tmp.bottom = Math.max(tmp.bottom, insets.bottom);
if (isRight)
tmp.right = Math.max(tmp.right, insets.right);
border.append(tmp, isReplace);
} else {
border.append(insets, isReplace);
}
table.setValueAt(myData, row, column);
}
}
table.clearSelection();
table.revalidate();
table.repaint();
}
}
class MyData implements CellBorder {
private Border border;
private Object obj;
public MyData(Object obj, Border border) {
this.obj = obj;
this.border = border;
}
public void setObject(Object obj) {
this.obj = obj;
}
public String toString() {
return obj.toString();
}
// CellBorder
public void setBorder(Border border) {
this.border = border;
}
public Border getBorder() {
return border;
}
public void setBorder(Border border, int row, int col) {
}
public Border getBorder(int row, int col) {
return null;
}
}
}
class BorderCellRenderer extends JLabel implements TableCellRenderer {
protected Border noFocusBorder;
protected Border columnBorder;
public BorderCellRenderer() {
noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setFont(table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
if (value instanceof CellBorder) {
Border border = ((CellBorder) value).getBorder();
setBorder(border);
} else {
if (columnBorder != null) {
setBorder(columnBorder);
} else {
setBorder(noFocusBorder);
}
}
}
setText((value == null) ? "" : value.toString());
return this;
}
public void setColumnBorder(Border border) {
columnBorder = border;
}
public Border getColumnBorder() {
return columnBorder;
}
}
interface CellBorder {
public Border getBorder();
public Border getBorder(int row, int column);
public void setBorder(Border border);
public void setBorder(Border border, int row, int column);
}
class LinesBorder extends AbstractBorder implements SwingConstants {
protected int northThickness;
protected int southThickness;
protected int eastThickness;
protected int westThickness;
protected Color northColor;
protected Color southColor;
protected Color eastColor;
protected Color westColor;
public LinesBorder(Color color) {
this(color, 1);
}
public LinesBorder(Color color, int thickness) {
setColor(color);
setThickness(thickness);
}
public LinesBorder(Color color, Insets insets) {
setColor(color);
setThickness(insets);
}
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
Color oldColor = g.getColor();
g.setColor(northColor);
for (int i = 0; i < northThickness; i++) {
g.drawLine(x, y + i, x + width - 1, y + i);
}
g.setColor(southColor);
for (int i = 0; i < southThickness; i++) {
g
.drawLine(x, y + height - i - 1, x + width - 1, y + height
- i - 1);
}
g.setColor(eastColor);
for (int i = 0; i < westThickness; i++) {
g.drawLine(x + i, y, x + i, y + height - 1);
}
g.setColor(westColor);
for (int i = 0; i < eastThickness; i++) {
g.drawLine(x + width - i - 1, y, x + width - i - 1, y + height - 1);
}
g.setColor(oldColor);
}
public Insets getBorderInsets(Component c) {
return new Insets(northThickness, westThickness, southThickness,
eastThickness);
}
public Insets getBorderInsets(Component c, Insets insets) {
return new Insets(northThickness, westThickness, southThickness,
eastThickness);
}
public boolean isBorderOpaque() {
return true;
}
public void setColor(Color c) {
northColor = c;
southColor = c;
eastColor = c;
westColor = c;
}
public void setColor(Color c, int direction) {
switch (direction) {
case NORTH:
northColor = c;
break;
case SOUTH:
southColor = c;
break;
case EAST:
eastColor = c;
break;
case WEST:
westColor = c;
break;
default:
}
}
public void setThickness(int n) {
northThickness = n;
southThickness = n;
eastThickness = n;
westThickness = n;
}
public void setThickness(Insets insets) {
northThickness = insets.top;
southThickness = insets.bottom;
eastThickness = insets.right;
westThickness = insets.left;
}
public void setThickness(int n, int direction) {
switch (direction) {
case NORTH:
northThickness = n;
break;
case SOUTH:
southThickness = n;
break;
case EAST:
eastThickness = n;
break;
case WEST:
westThickness = n;
break;
default:
}
}
public void append(LinesBorder b, boolean isReplace) {
if (isReplace) {
northThickness = b.northThickness;
southThickness = b.southThickness;
eastThickness = b.eastThickness;
westThickness = b.westThickness;
} else {
northThickness = Math.max(northThickness, b.northThickness);
southThickness = Math.max(southThickness, b.southThickness);
eastThickness = Math.max(eastThickness, b.eastThickness);
westThickness = Math.max(westThickness, b.westThickness);
}
}
public void append(Insets insets, boolean isReplace) {
if (isReplace) {
northThickness = insets.top;
southThickness = insets.bottom;
eastThickness = insets.right;
westThickness = insets.left;
} else {
northThickness = Math.max(northThickness, insets.top);
southThickness = Math.max(southThickness, insets.bottom);
eastThickness = Math.max(eastThickness, insets.right);
westThickness = Math.max(westThickness, insets.left);
}
}
}
Colored Cell Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
* (swing1.1beta3)
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
* @version 1.0 11/22/98
*/
public class ColoredCellTableExample extends JFrame {
private JTable table;
private ColoredCell cellAtt;
public ColoredCellTableExample() {
super("Colored Cell Example");
AttributiveCellTableModel ml = new AttributiveCellTableModel(10, 6);
cellAtt = (ColoredCell) ml.getCellAttribute();
table = new JTable(ml);
table.setCellSelectionEnabled(true);
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setDefaultRenderer(Object.class, new AttributiveCellRenderer());
JScrollPane scroll = new JScrollPane(table);
JButton b_fore = new JButton("Foreground");
b_fore.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeColor(true);
}
});
JButton b_back = new JButton("Background");
b_back.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeColor(false);
}
});
JPanel p_buttons = new JPanel();
p_buttons.setLayout(new GridLayout(2, 1));
p_buttons.add(b_fore);
p_buttons.add(b_back);
Box box = new Box(BoxLayout.X_AXIS);
box.add(scroll);
box.add(new JSeparator(SwingConstants.HORIZONTAL));
box.add(p_buttons);
getContentPane().add(box);
setSize(400, 200);
setVisible(true);
}
private final void changeColor(boolean isForeground) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
if ((rows == null) || (columns == null))
return;
if ((rows.length < 1) || (columns.length < 1))
return;
Color target = cellAtt.getForeground(rows[0], columns[0]);
Color reference = cellAtt.getBackground(rows[0], columns[0]);
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
for (int j = 0; j < columns.length; j++) {
int column = columns[j];
target = (target != cellAtt.getForeground(row, column)) ? null
: target;
reference = (reference != cellAtt.getBackground(row, column)) ? null
: reference;
}
}
String title;
if (isForeground) {
target = (target != null) ? target : table.getForeground();
reference = (reference != null) ? reference : table.getBackground();
title = "Foreground Color";
} else {
target = (reference != null) ? reference : table.getBackground();
reference = (target != null) ? target : table.getForeground();
title = "Foreground Color";
}
TextColorChooser chooser = new TextColorChooser(target, reference,
isForeground);
Color color = chooser.showDialog(ColoredCellTableExample.this, title);
if (color != null) {
if (isForeground) {
cellAtt.setForeground(color, rows, columns);
} else {
cellAtt.setBackground(color, rows, columns);
}
table.clearSelection();
table.revalidate();
table.repaint();
}
}
public static void main(String[] args) {
ColoredCellTableExample frame = new ColoredCellTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/22/98
*/
class AttributiveCellTableModel extends DefaultTableModel {
protected CellAttribute cellAtt;
public AttributiveCellTableModel() {
this((Vector) null, 0);
}
public AttributiveCellTableModel(int numRows, int numColumns) {
Vector names = new Vector(numColumns);
names.setSize(numColumns);
setColumnIdentifiers(names);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, numColumns);
}
public AttributiveCellTableModel(Vector columnNames, int numRows) {
setColumnIdentifiers(columnNames);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
}
public AttributiveCellTableModel(Object[] columnNames, int numRows) {
this(convertToVector(columnNames), numRows);
}
public AttributiveCellTableModel(Vector data, Vector columnNames) {
setDataVector(data, columnNames);
}
public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
public void setDataVector(Vector newData, Vector columnNames) {
if (newData == null)
throw new IllegalArgumentException("setDataVector() - Null parameter");
dataVector = new Vector(0);
setColumnIdentifiers(columnNames);
dataVector = newData;
//
cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
.size());
newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public void addColumn(Object columnName, Vector columnData) {
if (columnName == null)
throw new IllegalArgumentException("addColumn() - null parameter");
columnIdentifiers.addElement(columnName);
int index = 0;
Enumeration eeration = dataVector.elements();
while (eeration.hasMoreElements()) {
Object value;
if ((columnData != null) && (index < columnData.size()))
value = columnData.elementAt(index);
else
value = null;
((Vector) eeration.nextElement()).addElement(value);
index++;
}
//
cellAtt.addColumn();
fireTableStructureChanged();
}
public void addRow(Vector rowData) {
Vector newData = null;
if (rowData == null) {
newData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.addElement(newData);
//
cellAtt.addRow();
newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT));
}
public void insertRow(int row, Vector rowData) {
if (rowData == null) {
rowData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.insertElementAt(rowData, row);
//
cellAtt.insertRow(row);
newRowsAdded(new TableModelEvent(this, row, row,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public CellAttribute getCellAttribute() {
return cellAtt;
}
public void setCellAttribute(CellAttribute newCellAtt) {
int numColumns = getColumnCount();
int numRows = getRowCount();
if ((newCellAtt.getSize().width != numColumns)
|| (newCellAtt.getSize().height != numRows)) {
newCellAtt.setSize(new Dimension(numRows, numColumns));
}
cellAtt = newCellAtt;
fireTableDataChanged();
}
/*
* public void changeCellAttribute(int row, int column, Object command) {
* cellAtt.changeAttribute(row, column, command); }
*
* public void changeCellAttribute(int[] rows, int[] columns, Object
* command) { cellAtt.changeAttribute(rows, columns, command); }
*/
}
/**
* @version 1.0 11/22/98
*/
class DefaultCellAttribute
// implements CellAttribute ,CellSpan {
implements CellAttribute, CellSpan, ColoredCell, CellFont {
//
// !!!! CAUTION !!!!!
// these values must be synchronized to Table data
//
protected int rowSize;
protected int columnSize;
protected int[][][] span; // CellSpan
protected Color[][] foreground; // ColoredCell
protected Color[][] background; //
protected Font[][] font; // CellFont
public DefaultCellAttribute() {
this(1, 1);
}
public DefaultCellAttribute(int numRows, int numColumns) {
setSize(new Dimension(numColumns, numRows));
}
protected void initValue() {
for (int i = 0; i < span.length; i++) {
for (int j = 0; j < span[i].length; j++) {
span[i][j][CellSpan.COLUMN] = 1;
span[i][j][CellSpan.ROW] = 1;
}
}
}
//
// CellSpan
//
public int[] getSpan(int row, int column) {
if (isOutOfBounds(row, column)) {
int[] ret_code = { 1, 1 };
return ret_code;
}
return span[row][column];
}
public void setSpan(int[] span, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.span[row][column] = span;
}
public boolean isVisible(int row, int column) {
if (isOutOfBounds(row, column))
return false;
if ((span[row][column][CellSpan.COLUMN] < 1)
|| (span[row][column][CellSpan.ROW] < 1))
return false;
return true;
}
public void combine(int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
int rowSpan = rows.length;
int columnSpan = columns.length;
int startRow = rows[0];
int startColumn = columns[0];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
|| (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
//System.out.println("can"t combine");
return;
}
}
}
for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
//System.out.println("r " +ii +" c " +jj);
}
}
span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
span[startRow][startColumn][CellSpan.ROW] = rowSpan;
}
public void split(int row, int column) {
if (isOutOfBounds(row, column))
return;
int columnSpan = span[row][column][CellSpan.COLUMN];
int rowSpan = span[row][column][CellSpan.ROW];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
span[row + i][column + j][CellSpan.COLUMN] = 1;
span[row + i][column + j][CellSpan.ROW] = 1;
}
}
}
//
// ColoredCell
//
public Color getForeground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return foreground[row][column];
}
public void setForeground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
foreground[row][column] = color;
}
public void setForeground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(foreground, color, rows, columns);
}
public Color getBackground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return background[row][column];
}
public void setBackground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
background[row][column] = color;
}
public void setBackground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(background, color, rows, columns);
}
//
//
// CellFont
//
public Font getFont(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return font[row][column];
}
public void setFont(Font font, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.font[row][column] = font;
}
public void setFont(Font font, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(this.font, font, rows, columns);
}
//
//
// CellAttribute
//
public void addColumn() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows][numColumns + 1][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numRows; i++) {
span[i][numColumns][CellSpan.COLUMN] = 1;
span[i][numColumns][CellSpan.ROW] = 1;
}
}
public void addRow() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numColumns; i++) {
span[numRows][i][CellSpan.COLUMN] = 1;
span[numRows][i][CellSpan.ROW] = 1;
}
}
public void insertRow(int row) {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
if (0 < row) {
System.arraycopy(oldSpan, 0, span, 0, row - 1);
}
System.arraycopy(oldSpan, 0, span, row, numRows - row);
for (int i = 0; i < numColumns; i++) {
span[row][i][CellSpan.COLUMN] = 1;
span[row][i][CellSpan.ROW] = 1;
}
}
public Dimension getSize() {
return new Dimension(rowSize, columnSize);
}
public void setSize(Dimension size) {
columnSize = size.width;
rowSize = size.height;
span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
foreground = new Color[rowSize][columnSize];
background = new Color[rowSize][columnSize];
font = new Font[rowSize][columnSize];
initValue();
}
/*
* public void changeAttribute(int row, int column, Object command) { }
*
* public void changeAttribute(int[] rows, int[] columns, Object command) { }
*/
protected boolean isOutOfBounds(int row, int column) {
if ((row < 0) || (rowSize <= row) || (column < 0)
|| (columnSize <= column)) {
return true;
}
return false;
}
protected boolean isOutOfBounds(int[] rows, int[] columns) {
for (int i = 0; i < rows.length; i++) {
if ((rows[i] < 0) || (rowSize <= rows[i]))
return true;
}
for (int i = 0; i < columns.length; i++) {
if ((columns[i] < 0) || (columnSize <= columns[i]))
return true;
}
return false;
}
protected void setValues(Object[][] target, Object value, int[] rows,
int[] columns) {
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
for (int j = 0; j < columns.length; j++) {
int column = columns[j];
target[row][column] = value;
}
}
}
}
/**
* @version 1.0 11/22/98
*/
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/22/98
*/
interface CellAttribute {
public void addColumn();
public void addRow();
public void insertRow(int row);
public Dimension getSize();
public void setSize(Dimension size);
}
interface ColoredCell {
public Color getForeground(int row, int column);
public void setForeground(Color color, int row, int column);
public void setForeground(Color color, int[] rows, int[] columns);
public Color getBackground(int row, int column);
public void setBackground(Color color, int row, int column);
public void setBackground(Color color, int[] rows, int[] columns);
}
/**
* @version 1.0 11/22/98
*/
class AttributiveCellRenderer extends JLabel implements TableCellRenderer {
protected static Border noFocusBorder;
public AttributiveCellRenderer() {
noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setOpaque(true);
setBorder(noFocusBorder);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Color foreground = null;
Color background = null;
Font font = null;
TableModel model = table.getModel();
if (model instanceof AttributiveCellTableModel) {
CellAttribute cellAtt = ((AttributiveCellTableModel) model)
.getCellAttribute();
if (cellAtt instanceof ColoredCell) {
foreground = ((ColoredCell) cellAtt).getForeground(row, column);
background = ((ColoredCell) cellAtt).getBackground(row, column);
}
if (cellAtt instanceof CellFont) {
font = ((CellFont) cellAtt).getFont(row, column);
}
}
if (isSelected) {
setForeground((foreground != null) ? foreground : table
.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground((foreground != null) ? foreground : table
.getForeground());
setBackground((background != null) ? background : table
.getBackground());
}
setFont((font != null) ? font : table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground((foreground != null) ? foreground : UIManager
.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(noFocusBorder);
}
setValue(value);
return this;
}
protected void setValue(Object value) {
setText((value == null) ? "" : value.toString());
}
}
/**
* @version 1.0 11/22/98
*/
class TextPreviewLabel extends JLabel {
private String sampleText = " Sample Text Sample Text ";
boolean isForgroundSelection;
public TextPreviewLabel() {
this(Color.black, Color.white, true);
}
public TextPreviewLabel(Color fore, Color back, boolean isForgroundSelection) {
setOpaque(true);
setForeground(fore);
setBackground(back);
this.isForgroundSelection = isForgroundSelection;
setText(sampleText);
}
public void setForeground(Color col) {
if (isForgroundSelection) {
super.setForeground(col);
} else {
super.setBackground(col);
}
}
}
class ColorChooserDialog extends JDialog {
private Color initialColor;
private Color retColor;
private JColorChooser chooserPane;
public ColorChooserDialog(Component c, String title,
final JColorChooser chooserPane) {
super(JOptionPane.getFrameForComponent(c), title, true);
setResizable(false);
this.chooserPane = chooserPane;
String okString = UIManager.getString("ColorChooser.okText");
String cancelString = UIManager.getString("ColorChooser.cancelText");
String resetString = UIManager.getString("ColorChooser.resetText");
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(chooserPane, BorderLayout.CENTER);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
JButton okButton = new JButton(okString);
getRootPane().setDefaultButton(okButton);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
retColor = chooserPane.getColor();
setVisible(false);
}
});
buttonPane.add(okButton);
JButton cancelButton = new JButton(cancelString);
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
retColor = null;
setVisible(false);
}
});
buttonPane.add(cancelButton);
JButton resetButton = new JButton(resetString);
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
chooserPane.setColor(initialColor);
}
});
buttonPane.add(resetButton);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(c);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
}
});
}
public Color getColor() {
return retColor;
}
}
class TextColorChooser extends JColorChooser {
public TextColorChooser(Color target, Color reference,
boolean isForgroundSelection) {
super(target);
if (isForgroundSelection) {
setPreviewPanel(new TextPreviewLabel(target, reference,
isForgroundSelection));
} else {
setPreviewPanel(new TextPreviewLabel(reference, target,
isForgroundSelection));
}
updateUI();
}
public Color showDialog(Component component, String title) {
ColorChooserDialog dialog = new ColorChooserDialog(component, title,
this);
dialog.show();
Color col = dialog.getColor();
dialog.dispose();
return col;
}
}
interface CellFont {
public Font getFont(int row, int column);
public void setFont(Font font, int row, int column);
public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
public final int ROW = 0;
public final int COLUMN = 1;
public int[] getSpan(int row, int column);
public void setSpan(int[] span, int row, int column);
public boolean isVisible(int row, int column);
public void combine(int[] rows, int[] columns);
public void split(int row, int column);
}
Column Border Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/**
* @version 1.0 3/06/99
*/
public class ColumnBorderTableExample extends JFrame {
public ColumnBorderTableExample() {
super("Column Border Example");
DefaultTableModel dm = new DefaultTableModel(4, 10);
JTable table = new JTable(dm);
table.setIntercellSpacing(new Dimension(0, 0));
Color color = table.getGridColor();
BorderCellRenderer[] renderers = new BorderCellRenderer[6];
renderers[0] = createRenderer(color, new Insets(0, 0, 0, 1));
renderers[1] = createRenderer(color, new Insets(0, 1, 0, 1));
renderers[2] = createRenderer(color, new Insets(0, 1, 0, 2));
renderers[3] = createRenderer(color, new Insets(0, 2, 0, 2));
renderers[4] = createRenderer(color, new Insets(0, 2, 0, 0));
renderers[5] = createRenderer(Color.red, new Insets(0, 1, 1, 1));
TableColumnModel model = table.getColumnModel();
model.getColumn(1).setCellRenderer(renderers[0]);
model.getColumn(2).setCellRenderer(renderers[0]);
model.getColumn(3).setCellRenderer(renderers[0]);
model.getColumn(4).setCellRenderer(renderers[1]);
model.getColumn(5).setCellRenderer(renderers[2]);
model.getColumn(6).setCellRenderer(renderers[3]);
model.getColumn(7).setCellRenderer(renderers[4]);
model.getColumn(8).setCellRenderer(renderers[5]);
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll, BorderLayout.CENTER);
}
public static void main(String[] args) {
ColumnBorderTableExample frame = new ColumnBorderTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(300, 120);
frame.setVisible(true);
}
private static BorderCellRenderer createRenderer(Color color, Insets insets) {
BorderCellRenderer renderer = new BorderCellRenderer();
renderer.setColumnBorder(new LinesBorder(color, insets));
return renderer;
}
}
class BorderCellRenderer extends JLabel implements TableCellRenderer {
protected Border noFocusBorder;
protected Border columnBorder;
public BorderCellRenderer() {
noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setFont(table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
if (value instanceof CellBorder) {
Border border = ((CellBorder) value).getBorder();
setBorder(border);
} else {
if (columnBorder != null) {
setBorder(columnBorder);
} else {
setBorder(noFocusBorder);
}
}
}
setText((value == null) ? "" : value.toString());
return this;
}
public void setColumnBorder(Border border) {
columnBorder = border;
}
public Border getColumnBorder() {
return columnBorder;
}
}
interface CellBorder {
public Border getBorder();
public Border getBorder(int row, int column);
public void setBorder(Border border);
public void setBorder(Border border, int row, int column);
}
class LinesBorder extends AbstractBorder implements SwingConstants {
protected int northThickness;
protected int southThickness;
protected int eastThickness;
protected int westThickness;
protected Color northColor;
protected Color southColor;
protected Color eastColor;
protected Color westColor;
public LinesBorder(Color color) {
this(color, 1);
}
public LinesBorder(Color color, int thickness) {
setColor(color);
setThickness(thickness);
}
public LinesBorder(Color color, Insets insets) {
setColor(color);
setThickness(insets);
}
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
Color oldColor = g.getColor();
g.setColor(northColor);
for (int i = 0; i < northThickness; i++) {
g.drawLine(x, y + i, x + width - 1, y + i);
}
g.setColor(southColor);
for (int i = 0; i < southThickness; i++) {
g
.drawLine(x, y + height - i - 1, x + width - 1, y + height
- i - 1);
}
g.setColor(eastColor);
for (int i = 0; i < westThickness; i++) {
g.drawLine(x + i, y, x + i, y + height - 1);
}
g.setColor(westColor);
for (int i = 0; i < eastThickness; i++) {
g.drawLine(x + width - i - 1, y, x + width - i - 1, y + height - 1);
}
g.setColor(oldColor);
}
public Insets getBorderInsets(Component c) {
return new Insets(northThickness, westThickness, southThickness,
eastThickness);
}
public Insets getBorderInsets(Component c, Insets insets) {
return new Insets(northThickness, westThickness, southThickness,
eastThickness);
}
public boolean isBorderOpaque() {
return true;
}
public void setColor(Color c) {
northColor = c;
southColor = c;
eastColor = c;
westColor = c;
}
public void setColor(Color c, int direction) {
switch (direction) {
case NORTH:
northColor = c;
break;
case SOUTH:
southColor = c;
break;
case EAST:
eastColor = c;
break;
case WEST:
westColor = c;
break;
default:
}
}
public void setThickness(int n) {
northThickness = n;
southThickness = n;
eastThickness = n;
westThickness = n;
}
public void setThickness(Insets insets) {
northThickness = insets.top;
southThickness = insets.bottom;
eastThickness = insets.right;
westThickness = insets.left;
}
public void setThickness(int n, int direction) {
switch (direction) {
case NORTH:
northThickness = n;
break;
case SOUTH:
southThickness = n;
break;
case EAST:
eastThickness = n;
break;
case WEST:
westThickness = n;
break;
default:
}
}
public void append(LinesBorder b, boolean isReplace) {
if (isReplace) {
northThickness = b.northThickness;
southThickness = b.southThickness;
eastThickness = b.eastThickness;
westThickness = b.westThickness;
} else {
northThickness = Math.max(northThickness, b.northThickness);
southThickness = Math.max(southThickness, b.southThickness);
eastThickness = Math.max(eastThickness, b.eastThickness);
westThickness = Math.max(westThickness, b.westThickness);
}
}
public void append(Insets insets, boolean isReplace) {
if (isReplace) {
northThickness = insets.top;
southThickness = insets.bottom;
eastThickness = insets.right;
westThickness = insets.left;
} else {
northThickness = Math.max(northThickness, insets.top);
southThickness = Math.max(southThickness, insets.bottom);
eastThickness = Math.max(eastThickness, insets.right);
westThickness = Math.max(westThickness, insets.left);
}
}
}
(From http://swinglabs.org/downloads.jsp)
ComboBox Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import javax.swing.*;
import javax.swing.table.*;
import java.awt.event.*;
public class ComboBoxTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Combo Box Table");
JTable tbl = new JTable(new ComboBoxTableModel());
// Create the combo box editor
JComboBox comboBox = new JComboBox(ComboBoxTableModel.getValidStates());
comboBox.setEditable(true);
DefaultCellEditor editor = new DefaultCellEditor(comboBox);
// Assign the editor to the second column
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(1).setCellEditor(editor);
// Set column widths
tcm.getColumn(0).setPreferredWidth(200);
tcm.getColumn(1).setPreferredWidth(100);
// Set row heighht
tbl.setRowHeight(20);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
f.getContentPane().add(new JScrollPane(tbl), "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class ComboBoxTableModel extends AbstractTableModel {
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
public boolean isCellEditable(int row, int column) {
return column == 1;
}
public void setValueAt(Object value, int row, int column) {
if (isValidValue(value)) {
data[row][column] = value;
fireTableRowsUpdated(row, row);
}
}
// Extra public methods
public static String[] getValidStates() {
return validStates;
}
// Protected methods
protected boolean isValidValue(Object value) {
if (value instanceof String) {
String sValue = (String)value;
for (int i = 0; i < validStates.length; i++) {
if (sValue.equals(validStates[i])) {
return true;
}
}
}
return false;
}
protected static final int COLUMN_COUNT = 2;
protected static final String[] validStates = {
"On order", "In stock", "Out of print"
};
protected Object[][] data = new Object[][] {
{ "Core Java Volume 1", validStates[0] },
{ "Core Java Volume 2", validStates[0] },
{ "Core Web Programming", validStates[0] },
{ "Core Visual Basic 5", validStates[0] },
{ "Core Java Foundation Classes", validStates[0] }
};
protected static final String[] columnNames = {
"Book Name", "Status"
};
}
CurrencyTable
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
public class CurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Currency Table");
JTable tbl = new JTable(new CurrencyTableModel());
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
Each Row with different Editor Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1) */
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.event.ruponentAdapter;
import java.awt.event.ruponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import java.util.Hashtable;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
/**
* @version 1.1 09/09/99
*/
public class EachRowEditorExample extends JFrame {
public EachRowEditorExample() {
super("EachRow Editor Example");
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][] { { "Name", "MyName" },
{ "Gender", "Male" } }, new Object[] { "Column1", "Column2" });
JTable table = new JTable(dm);
JComboBox comboBox = new JComboBox();
comboBox.addItem("Male");
comboBox.addItem("Female");
comboBox.addComponentListener(new ComponentAdapter() {
public void componentShown(ComponentEvent e) {
final JComponent c = (JComponent) e.getSource();
SwingUtilities.invokeLater(new Runnable() {
public void run() {
c.requestFocus();
System.out.println(c);
if (c instanceof JComboBox) {
System.out.println("a");
}
}
});
}
});
EachRowEditor rowEditor = new EachRowEditor(table);
rowEditor.setEditorAt(1, new DefaultCellEditor(comboBox));
table.getColumn("Column2").setCellEditor(rowEditor);
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll, BorderLayout.CENTER);
setSize(400, 100);
setVisible(true);
}
public static void main(String[] args) {
EachRowEditorExample frame = new EachRowEditorExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/**
* each row TableCellEditor
*
* @version 1.1 09/09/99
* @author Nobuo Tamemasa
*/
class EachRowEditor implements TableCellEditor {
protected Hashtable editors;
protected TableCellEditor editor, defaultEditor;
JTable table;
/**
* Constructs a EachRowEditor. create default editor
*
* @see TableCellEditor
* @see DefaultCellEditor
*/
public EachRowEditor(JTable table) {
this.table = table;
editors = new Hashtable();
defaultEditor = new DefaultCellEditor(new JTextField());
}
/**
* @param row
* table row
* @param editor
* table cell editor
*/
public void setEditorAt(int row, TableCellEditor editor) {
editors.put(new Integer(row), editor);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//editor = (TableCellEditor)editors.get(new Integer(row));
//if (editor == null) {
// editor = defaultEditor;
//}
return editor.getTableCellEditorComponent(table, value, isSelected,
row, column);
}
public Object getCellEditorValue() {
return editor.getCellEditorValue();
}
public boolean stopCellEditing() {
return editor.stopCellEditing();
}
public void cancelCellEditing() {
editor.cancelCellEditing();
}
public boolean isCellEditable(EventObject anEvent) {
selectEditor((MouseEvent) anEvent);
return editor.isCellEditable(anEvent);
}
public void addCellEditorListener(CellEditorListener l) {
editor.addCellEditorListener(l);
}
public void removeCellEditorListener(CellEditorListener l) {
editor.removeCellEditorListener(l);
}
public boolean shouldSelectCell(EventObject anEvent) {
selectEditor((MouseEvent) anEvent);
return editor.shouldSelectCell(anEvent);
}
protected void selectEditor(MouseEvent e) {
int row;
if (e == null) {
row = table.getSelectionModel().getAnchorSelectionIndex();
} else {
row = table.rowAtPoint(e.getPoint());
}
editor = (TableCellEditor) editors.get(new Integer(row));
if (editor == null) {
editor = defaultEditor;
}
}
}
Editable Header Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.ruponent;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.basic.BasicTableHeaderUI;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* @version 1.0 08/22/99
*/
public class EditableHeaderTableExample extends JFrame {
public EditableHeaderTableExample() {
super("EditableHeader Example");
JTable table = new JTable(7, 5);
TableColumnModel columnModel = table.getColumnModel();
table.setTableHeader(new EditableHeader(columnModel));
JScrollPane pane = new JScrollPane(table);
getContentPane().add(pane);
}
public static void main(String[] args) {
EditableHeaderTableExample frame = new EditableHeaderTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(300, 100);
frame.setVisible(true);
}
}
class EditableHeader extends JTableHeader implements CellEditorListener {
public final int HEADER_ROW = -10;
transient protected int editingColumn;
transient protected TableCellEditor cellEditor;
transient protected Component editorComp;
public EditableHeader(TableColumnModel columnModel) {
super(columnModel);
setReorderingAllowed(false);
cellEditor = null;
recreateTableColumn(columnModel);
}
public void updateUI() {
setUI(new EditableHeaderUI());
resizeAndRepaint();
invalidate();
}
protected void recreateTableColumn(TableColumnModel columnModel) {
int n = columnModel.getColumnCount();
EditableHeaderTableColumn[] newCols = new EditableHeaderTableColumn[n];
TableColumn[] oldCols = new TableColumn[n];
for (int i = 0; i < n; i++) {
oldCols[i] = columnModel.getColumn(i);
newCols[i] = new EditableHeaderTableColumn();
newCols[i].copyValues(oldCols[i]);
}
for (int i = 0; i < n; i++) {
columnModel.removeColumn(oldCols[i]);
}
for (int i = 0; i < n; i++) {
columnModel.addColumn(newCols[i]);
}
}
public boolean editCellAt(int index) {
return editCellAt(index);
}
public boolean editCellAt(int index, EventObject e) {
if (cellEditor != null && !cellEditor.stopCellEditing()) {
return false;
}
if (!isCellEditable(index)) {
return false;
}
TableCellEditor editor = getCellEditor(index);
if (editor != null && editor.isCellEditable(e)) {
editorComp = prepareEditor(editor, index);
editorComp.setBounds(getHeaderRect(index));
add(editorComp);
editorComp.validate();
setCellEditor(editor);
setEditingColumn(index);
editor.addCellEditorListener(this);
return true;
}
return false;
}
public boolean isCellEditable(int index) {
if (getReorderingAllowed()) {
return false;
}
int columnIndex = columnModel.getColumn(index).getModelIndex();
EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
.getColumn(columnIndex);
return col.isHeaderEditable();
}
public TableCellEditor getCellEditor(int index) {
int columnIndex = columnModel.getColumn(index).getModelIndex();
EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
.getColumn(columnIndex);
return col.getHeaderEditor();
}
public void setCellEditor(TableCellEditor newEditor) {
TableCellEditor oldEditor = cellEditor;
cellEditor = newEditor;
// firePropertyChange
if (oldEditor != null && oldEditor instanceof TableCellEditor) {
((TableCellEditor) oldEditor)
.removeCellEditorListener((CellEditorListener) this);
}
if (newEditor != null && newEditor instanceof TableCellEditor) {
((TableCellEditor) newEditor)
.addCellEditorListener((CellEditorListener) this);
}
}
public Component prepareEditor(TableCellEditor editor, int index) {
Object value = columnModel.getColumn(index).getHeaderValue();
boolean isSelected = true;
int row = HEADER_ROW;
JTable table = getTable();
Component comp = editor.getTableCellEditorComponent(table, value,
isSelected, row, index);
if (comp instanceof JComponent) {
((JComponent) comp).setNextFocusableComponent(this);
}
return comp;
}
public TableCellEditor getCellEditor() {
return cellEditor;
}
public Component getEditorComponent() {
return editorComp;
}
public void setEditingColumn(int aColumn) {
editingColumn = aColumn;
}
public int getEditingColumn() {
return editingColumn;
}
public void removeEditor() {
TableCellEditor editor = getCellEditor();
if (editor != null) {
editor.removeCellEditorListener(this);
requestFocus();
remove(editorComp);
int index = getEditingColumn();
Rectangle cellRect = getHeaderRect(index);
setCellEditor(null);
setEditingColumn(-1);
editorComp = null;
repaint(cellRect);
}
}
public boolean isEditing() {
return (cellEditor == null) ? false : true;
}
//
// CellEditorListener
//
public void editingStopped(ChangeEvent e) {
TableCellEditor editor = getCellEditor();
if (editor != null) {
Object value = editor.getCellEditorValue();
int index = getEditingColumn();
columnModel.getColumn(index).setHeaderValue(value);
removeEditor();
}
}
public void editingCanceled(ChangeEvent e) {
removeEditor();
}
//
// public void setReorderingAllowed(boolean b) {
// reorderingAllowed = false;
// }
}
class EditableHeaderUI extends BasicTableHeaderUI {
protected MouseInputListener createMouseInputListener() {
return new MouseInputHandler((EditableHeader) header);
}
public class MouseInputHandler extends BasicTableHeaderUI.MouseInputHandler {
private Component dispatchComponent;
protected EditableHeader header;
public MouseInputHandler(EditableHeader header) {
this.header = header;
}
private void setDispatchComponent(MouseEvent e) {
Component editorComponent = header.getEditorComponent();
Point p = e.getPoint();
Point p2 = SwingUtilities.convertPoint(header, p, editorComponent);
dispatchComponent = SwingUtilities.getDeepestComponentAt(
editorComponent, p2.x, p2.y);
}
private boolean repostEvent(MouseEvent e) {
if (dispatchComponent == null) {
return false;
}
MouseEvent e2 = SwingUtilities.convertMouseEvent(header, e,
dispatchComponent);
dispatchComponent.dispatchEvent(e2);
return true;
}
public void mousePressed(MouseEvent e) {
if (!SwingUtilities.isLeftMouseButton(e)) {
return;
}
super.mousePressed(e);
if (header.getResizingColumn() == null) {
Point p = e.getPoint();
TableColumnModel columnModel = header.getColumnModel();
int index = columnModel.getColumnIndexAtX(p.x);
if (index != -1) {
if (header.editCellAt(index, e)) {
setDispatchComponent(e);
repostEvent(e);
}
}
}
}
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
if (!SwingUtilities.isLeftMouseButton(e)) {
return;
}
repostEvent(e);
dispatchComponent = null;
}
}
}
class EditableHeaderTableColumn extends TableColumn {
protected TableCellEditor headerEditor;
protected boolean isHeaderEditable;
public EditableHeaderTableColumn() {
setHeaderEditor(createDefaultHeaderEditor());
isHeaderEditable = true;
}
public void setHeaderEditor(TableCellEditor headerEditor) {
this.headerEditor = headerEditor;
}
public TableCellEditor getHeaderEditor() {
return headerEditor;
}
public void setHeaderEditable(boolean isEditable) {
isHeaderEditable = isEditable;
}
public boolean isHeaderEditable() {
return isHeaderEditable;
}
public void copyValues(TableColumn base) {
modelIndex = base.getModelIndex();
identifier = base.getIdentifier();
width = base.getWidth();
minWidth = base.getMinWidth();
setPreferredWidth(base.getPreferredWidth());
maxWidth = base.getMaxWidth();
headerRenderer = base.getHeaderRenderer();
headerValue = base.getHeaderValue();
cellRenderer = base.getCellRenderer();
cellEditor = base.getCellEditor();
isResizable = base.getResizable();
}
protected TableCellEditor createDefaultHeaderEditor() {
return new DefaultCellEditor(new JTextField());
}
}
Editable Header Table Example 2
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.ruponent;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.basic.BasicTableHeaderUI;
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;
/**
* @version 1.0 08/22/99
*/
public class EditableHeaderTableExample2 extends JFrame {
public EditableHeaderTableExample2() {
super("EditableHeader Example");
JTable table = new JTable(7, 5);
TableColumnModel columnModel = table.getColumnModel();
table.setTableHeader(new EditableHeader(columnModel));
String[] items = { "Dog", "Cat" };
JComboBox combo = new JComboBox();
for (int i = 0; i < items.length; i++) {
combo.addItem(items[i]);
}
ComboRenderer renderer = new ComboRenderer(items);
EditableHeaderTableColumn col;
// column 1
col = (EditableHeaderTableColumn) table.getColumnModel().getColumn(1);
col.setHeaderValue(combo.getItemAt(0));
col.setHeaderRenderer(renderer);
col.setHeaderEditor(new DefaultCellEditor(combo));
// column 3
col = (EditableHeaderTableColumn) table.getColumnModel().getColumn(3);
col.setHeaderValue(combo.getItemAt(0));
//col.setHeaderRenderer(renderer);
col.setHeaderEditor(new DefaultCellEditor(combo));
JScrollPane pane = new JScrollPane(table);
getContentPane().add(pane);
}
class ComboRenderer extends JComboBox implements TableCellRenderer {
ComboRenderer(String[] items) {
for (int i = 0; i < items.length; i++) {
addItem(items[i]);
}
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
setSelectedItem(value);
return this;
}
}
public static void main(String[] args) {
EditableHeaderTableExample2 frame = new EditableHeaderTableExample2();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(300, 100);
frame.setVisible(true);
}
}
class EditableHeader extends JTableHeader implements CellEditorListener {
public final int HEADER_ROW = -10;
transient protected int editingColumn;
transient protected TableCellEditor cellEditor;
transient protected Component editorComp;
public EditableHeader(TableColumnModel columnModel) {
super(columnModel);
setReorderingAllowed(false);
cellEditor = null;
recreateTableColumn(columnModel);
}
public void updateUI() {
setUI(new EditableHeaderUI());
resizeAndRepaint();
invalidate();
}
protected void recreateTableColumn(TableColumnModel columnModel) {
int n = columnModel.getColumnCount();
EditableHeaderTableColumn[] newCols = new EditableHeaderTableColumn[n];
TableColumn[] oldCols = new TableColumn[n];
for (int i = 0; i < n; i++) {
oldCols[i] = columnModel.getColumn(i);
newCols[i] = new EditableHeaderTableColumn();
newCols[i].copyValues(oldCols[i]);
}
for (int i = 0; i < n; i++) {
columnModel.removeColumn(oldCols[i]);
}
for (int i = 0; i < n; i++) {
columnModel.addColumn(newCols[i]);
}
}
public boolean editCellAt(int index) {
return editCellAt(index);
}
public boolean editCellAt(int index, EventObject e) {
if (cellEditor != null && !cellEditor.stopCellEditing()) {
return false;
}
if (!isCellEditable(index)) {
return false;
}
TableCellEditor editor = getCellEditor(index);
if (editor != null && editor.isCellEditable(e)) {
editorComp = prepareEditor(editor, index);
editorComp.setBounds(getHeaderRect(index));
add(editorComp);
editorComp.validate();
setCellEditor(editor);
setEditingColumn(index);
editor.addCellEditorListener(this);
return true;
}
return false;
}
public boolean isCellEditable(int index) {
if (getReorderingAllowed()) {
return false;
}
int columnIndex = columnModel.getColumn(index).getModelIndex();
EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
.getColumn(columnIndex);
return col.isHeaderEditable();
}
public TableCellEditor getCellEditor(int index) {
int columnIndex = columnModel.getColumn(index).getModelIndex();
EditableHeaderTableColumn col = (EditableHeaderTableColumn) columnModel
.getColumn(columnIndex);
return col.getHeaderEditor();
}
public void setCellEditor(TableCellEditor newEditor) {
TableCellEditor oldEditor = cellEditor;
cellEditor = newEditor;
// firePropertyChange
if (oldEditor != null && oldEditor instanceof TableCellEditor) {
((TableCellEditor) oldEditor)
.removeCellEditorListener((CellEditorListener) this);
}
if (newEditor != null && newEditor instanceof TableCellEditor) {
((TableCellEditor) newEditor)
.addCellEditorListener((CellEditorListener) this);
}
}
public Component prepareEditor(TableCellEditor editor, int index) {
Object value = columnModel.getColumn(index).getHeaderValue();
boolean isSelected = true;
int row = HEADER_ROW;
JTable table = getTable();
Component comp = editor.getTableCellEditorComponent(table, value,
isSelected, row, index);
if (comp instanceof JComponent) {
((JComponent) comp).setNextFocusableComponent(this);
}
return comp;
}
public TableCellEditor getCellEditor() {
return cellEditor;
}
public Component getEditorComponent() {
return editorComp;
}
public void setEditingColumn(int aColumn) {
editingColumn = aColumn;
}
public int getEditingColumn() {
return editingColumn;
}
public void removeEditor() {
TableCellEditor editor = getCellEditor();
if (editor != null) {
editor.removeCellEditorListener(this);
requestFocus();
remove(editorComp);
int index = getEditingColumn();
Rectangle cellRect = getHeaderRect(index);
setCellEditor(null);
setEditingColumn(-1);
editorComp = null;
repaint(cellRect);
}
}
public boolean isEditing() {
return (cellEditor == null) ? false : true;
}
//
// CellEditorListener
//
public void editingStopped(ChangeEvent e) {
TableCellEditor editor = getCellEditor();
if (editor != null) {
Object value = editor.getCellEditorValue();
int index = getEditingColumn();
columnModel.getColumn(index).setHeaderValue(value);
removeEditor();
}
}
public void editingCanceled(ChangeEvent e) {
removeEditor();
}
//
// public void setReorderingAllowed(boolean b) {
// reorderingAllowed = false;
// }
}
class EditableHeaderUI extends BasicTableHeaderUI {
protected MouseInputListener createMouseInputListener() {
return new MouseInputHandler((EditableHeader) header);
}
public class MouseInputHandler extends BasicTableHeaderUI.MouseInputHandler {
private Component dispatchComponent;
protected EditableHeader header;
public MouseInputHandler(EditableHeader header) {
this.header = header;
}
private void setDispatchComponent(MouseEvent e) {
Component editorComponent = header.getEditorComponent();
Point p = e.getPoint();
Point p2 = SwingUtilities.convertPoint(header, p, editorComponent);
dispatchComponent = SwingUtilities.getDeepestComponentAt(
editorComponent, p2.x, p2.y);
}
private boolean repostEvent(MouseEvent e) {
if (dispatchComponent == null) {
return false;
}
MouseEvent e2 = SwingUtilities.convertMouseEvent(header, e,
dispatchComponent);
dispatchComponent.dispatchEvent(e2);
return true;
}
public void mousePressed(MouseEvent e) {
if (!SwingUtilities.isLeftMouseButton(e)) {
return;
}
super.mousePressed(e);
if (header.getResizingColumn() == null) {
Point p = e.getPoint();
TableColumnModel columnModel = header.getColumnModel();
int index = columnModel.getColumnIndexAtX(p.x);
if (index != -1) {
if (header.editCellAt(index, e)) {
setDispatchComponent(e);
repostEvent(e);
}
}
}
}
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
if (!SwingUtilities.isLeftMouseButton(e)) {
return;
}
repostEvent(e);
dispatchComponent = null;
}
}
}
class EditableHeaderTableColumn extends TableColumn {
protected TableCellEditor headerEditor;
protected boolean isHeaderEditable;
public EditableHeaderTableColumn() {
setHeaderEditor(createDefaultHeaderEditor());
isHeaderEditable = true;
}
public void setHeaderEditor(TableCellEditor headerEditor) {
this.headerEditor = headerEditor;
}
public TableCellEditor getHeaderEditor() {
return headerEditor;
}
public void setHeaderEditable(boolean isEditable) {
isHeaderEditable = isEditable;
}
public boolean isHeaderEditable() {
return isHeaderEditable;
}
public void copyValues(TableColumn base) {
modelIndex = base.getModelIndex();
identifier = base.getIdentifier();
width = base.getWidth();
minWidth = base.getMinWidth();
setPreferredWidth(base.getPreferredWidth());
maxWidth = base.getMaxWidth();
headerRenderer = base.getHeaderRenderer();
headerValue = base.getHeaderValue();
cellRenderer = base.getCellRenderer();
cellEditor = base.getCellEditor();
isResizable = base.getResizable();
}
protected TableCellEditor createDefaultHeaderEditor() {
return new DefaultCellEditor(new JTextField());
}
}
Editable Highlight Currency Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class EditableHighlightCurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Editable Highlighted Currency Table");
JTable tbl = new JTable(new EditableCurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tbl.setShowHorizontalLines(false);
tbl.setIntercellSpacing(new Dimension(1, 0));
// Add the stripe renderer in the leftmost four columns.
StripedTableCellRenderer.installInColumn(tbl, 0, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 1, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 2, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 3, Color.lightGray,
Color.white, null, null);
// Add the highlight renderer to the difference column.
// The following comparator makes it highlight
// cells with negative numeric values.
Comparator cmp = new Comparator() {
public boolean shouldHighlight(JTable tbl, Object value, int row,
int column) {
if (value instanceof Number) {
double columnValue = ((Number) value).doubleValue();
return columnValue < (double) 0.0;
}
return false;
}
};
tcm.getColumn(3).setCellRenderer(
new HighlightRenderer(cmp, null, Color.pink, Color.black,
Color.pink.darker(), Color.white));
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class EditableCurrencyTableModel extends CurrencyTableModel {
public boolean isCellEditable(int row, int column) {
return column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN;
}
public void setValueAt(Object value, int row, int column) {
try {
if (column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN) {
Double newObjectValue; // New value as an Object
double newValue; // double, for validity checking
if (value instanceof Number) {
// Convert Number to Double
newValue = ((Number) value).doubleValue();
newObjectValue = new Double(newValue);
} else if (value instanceof String) {
// Convert a String to a Double
newObjectValue = new Double((String) value);
newValue = newObjectValue.doubleValue();
} else {
// Unrecognized - ignore
return;
}
if (newValue > (double) 0.0) {
// Store new value, but reject zero or negative values
data[row][column] = newObjectValue;
data[row][DIFF_COLUMN] = new Double(
((Double) data[row][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[row][OLD_RATE_COLUMN])
.doubleValue());
fireTableRowsUpdated(row, row);
}
}
} catch (NumberFormatException e) {
// Ignore a badly-formatted number
}
}
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
interface Comparator {
public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
int column);
}
class HighlightRenderer implements TableCellRenderer {
public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
Color backColor, Color foreColor, Color highlightBack,
Color highlightFore) {
this.cmp = cmp;
this.targetRenderer = targetRenderer;
this.backColor = backColor;
this.foreColor = foreColor;
this.highlightBack = highlightBack;
this.highlightFore = highlightFore;
}
public Component getTableCellRendererComponent(JTable tbl, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
}
Component comp = renderer.getTableCellRendererComponent(tbl, value,
isSelected, hasFocus, row, column);
if (isSelected == false && hasFocus == false && value != null) {
if (cmp.shouldHighlight(tbl, value, row, column)) {
comp.setForeground(highlightFore);
comp.setBackground(highlightBack);
} else {
comp.setForeground(foreColor);
comp.setBackground(backColor);
}
}
return comp;
}
protected Comparator cmp;
protected TableCellRenderer targetRenderer;
protected Color backColor;
protected Color foreColor;
protected Color highlightBack;
protected Color highlightFore;
}
Fixed Table Column Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.UIManager;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.AbstractTableModel;
/**
* @version 1.0 12/05/98
*/
public class FixedColumnExample extends JFrame {
Object[][] data;
Object[] column;
JTable fixedTable, table;
public FixedColumnExample() {
super("Fixed Column Example");
setSize(400, 150);
data = new Object[][] { { "1", "11", "A", "", "", "", "", "" },
{ "2", "22", "", "B", "", "", "", "" },
{ "3", "33", "", "", "C", "", "", "" },
{ "4", "44", "", "", "", "D", "", "" },
{ "5", "55", "", "", "", "", "E", "" },
{ "6", "66", "", "", "", "", "", "F" } };
column = new Object[] { "fixed 1", "fixed 2", "a", "b", "c", "d", "e",
"f" };
AbstractTableModel fixedModel = new AbstractTableModel() {
public int getColumnCount() {
return 2;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return (String) column[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
};
AbstractTableModel model = new AbstractTableModel() {
public int getColumnCount() {
return column.length - 2;
}
public int getRowCount() {
return data.length;
}
public String getColumnName(int col) {
return (String) column[col + 2];
}
public Object getValueAt(int row, int col) {
return data[row][col + 2];
}
public void setValueAt(Object obj, int row, int col) {
data[row][col + 2] = obj;
}
public boolean CellEditable(int row, int col) {
return true;
}
};
fixedTable = new JTable(fixedModel) {
public void valueChanged(ListSelectionEvent e) {
super.valueChanged(e);
checkSelection(true);
}
};
table = new JTable(model) {
public void valueChanged(ListSelectionEvent e) {
super.valueChanged(e);
checkSelection(false);
}
};
fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane scroll = new JScrollPane(table);
JViewport viewport = new JViewport();
viewport.setView(fixedTable);
viewport.setPreferredSize(fixedTable.getPreferredSize());
scroll.setRowHeaderView(viewport);
scroll.setCorner(JScrollPane.UPPER_LEFT_CORNER, fixedTable
.getTableHeader());
getContentPane().add(scroll, BorderLayout.CENTER);
}
private void checkSelection(boolean isFixedTable) {
int fixedSelectedIndex = fixedTable.getSelectedRow();
int selectedIndex = table.getSelectedRow();
if (fixedSelectedIndex != selectedIndex) {
if (isFixedTable) {
table.setRowSelectionInterval(fixedSelectedIndex,
fixedSelectedIndex);
} else {
fixedTable
.setRowSelectionInterval(selectedIndex, selectedIndex);
}
}
}
public static void main(String[] args) {
FixedColumnExample frame = new FixedColumnExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
Fixed Table Row Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta1) */
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
/**
* @version 1.0 03/05/99
*/
public class FixedRowExample extends JFrame {
Object[][] data;
Object[] column;
JTable fixedTable, table;
private int FIXED_NUM = 2;
public FixedRowExample() {
super("Fixed Row Example");
data = new Object[][] { { "a", "", "", "", "", "" },
{ "", "b", "", "", "", "" }, { "", "", "c", "", "", "" },
{ "", "", "", "d", "", "" }, { "", "", "", "", "e", "" },
{ "", "", "", "", "", "f" },
{ "fixed1", "", "", "", "", "", "", "" },
{ "fixed2", "", "", "", "", "", "", "" } };
column = new Object[] { "A", "B", "C", "D", "E", "F" };
AbstractTableModel model = new AbstractTableModel() {
public int getColumnCount() {
return column.length;
}
public int getRowCount() {
return data.length - FIXED_NUM;
}
public String getColumnName(int col) {
return (String) column[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public void setValueAt(Object obj, int row, int col) {
data[row][col] = obj;
}
public boolean CellEditable(int row, int col) {
return true;
}
};
AbstractTableModel fixedModel = new AbstractTableModel() {
public int getColumnCount() {
return column.length;
}
public int getRowCount() {
return FIXED_NUM;
}
public Object getValueAt(int row, int col) {
return data[row + (data.length - FIXED_NUM)][col];
}
};
table = new JTable(model);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
fixedTable = new JTable(fixedModel);
fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane scroll = new JScrollPane(table);
scroll
.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JScrollPane fixedScroll = new JScrollPane(fixedTable) {
public void setColumnHeaderView(Component view) {
} // work around
}; //
// fixedScroll.setColumnHeader(null);
fixedScroll
.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
JScrollBar bar = fixedScroll.getVerticalScrollBar();
JScrollBar dummyBar = new JScrollBar() {
public void paint(Graphics g) {
}
};
dummyBar.setPreferredSize(bar.getPreferredSize());
fixedScroll.setVerticalScrollBar(dummyBar);
final JScrollBar bar1 = scroll.getHorizontalScrollBar();
JScrollBar bar2 = fixedScroll.getHorizontalScrollBar();
bar2.addAdjustmentListener(new AdjustmentListener() {
public void adjustmentValueChanged(AdjustmentEvent e) {
bar1.setValue(e.getValue());
}
});
scroll.setPreferredSize(new Dimension(400, 100));
fixedScroll.setPreferredSize(new Dimension(400, 52)); // Hmm...
getContentPane().add(scroll, BorderLayout.CENTER);
getContentPane().add(fixedScroll, BorderLayout.SOUTH);
}
public static void main(String[] args) {
FixedRowExample frame = new FixedRowExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
}
Fraction Currency Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
public class FractionCurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Fraction Currency Table");
JTable tbl = new JTable(new CurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
Groupable(Group) Header Example
/* (swing1.1beta3)
*example from
http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
*
*/
/* (swing1.1beta3)
*
* |-----------------------------------------------------|
* | | Name | Language |
* | |-----------------|--------------------------|
* | SNo. | | | | Others |
* | | 1 | 2 | Native |-----------------|
* | | | | | 2 | 3 |
* |-----------------------------------------------------|
* | | | | | | |
*
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* @version 1.0 11/09/98
*/
public class GroupableHeaderExample extends JFrame {
GroupableHeaderExample() {
super( "Groupable Header Example" );
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][]{
{"119","foo","bar","ja","ko","zh"},
{"911","bar","foo","en","fr","pt"}},
new Object[]{"SNo.","1","2","Native","2","3"});
JTable table = new JTable( dm ) {
protected JTableHeader createDefaultTableHeader() {
return new GroupableTableHeader(columnModel);
}
};
TableColumnModel cm = table.getColumnModel();
ColumnGroup g_name = new ColumnGroup("Name");
g_name.add(cm.getColumn(1));
g_name.add(cm.getColumn(2));
ColumnGroup g_lang = new ColumnGroup("Language");
g_lang.add(cm.getColumn(3));
ColumnGroup g_other = new ColumnGroup("Others");
g_other.add(cm.getColumn(4));
g_other.add(cm.getColumn(5));
g_lang.add(g_other);
GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
header.addColumnGroup(g_name);
header.addColumnGroup(g_lang);
JScrollPane scroll = new JScrollPane( table );
getContentPane().add( scroll );
setSize( 400, 120 );
}
public static void main(String[] args) {
GroupableHeaderExample frame = new GroupableHeaderExample();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
/*
* (swing1.1beta3)
*
*/
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* GroupableTableHeader
*
* @version 1.0 10/20/98
* @author Nobuo Tamemasa
*/
public class GroupableTableHeader extends JTableHeader {
private static final String uiClassID = "GroupableTableHeaderUI";
protected Vector columnGroups = null;
public GroupableTableHeader(TableColumnModel model) {
super(model);
setUI(new GroupableTableHeaderUI());
setReorderingAllowed(false);
}
public void updateUI(){
setUI(new GroupableTableHeaderUI());
}
public void setReorderingAllowed(boolean b) {
reorderingAllowed = false;
}
public void addColumnGroup(ColumnGroup g) {
if (columnGroups == null) {
columnGroups = new Vector();
}
columnGroups.addElement(g);
}
public Enumeration getColumnGroups(TableColumn col) {
if (columnGroups == null) return null;
Enumeration e = columnGroups.elements();
while (e.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)e.nextElement();
Vector v_ret = (Vector)cGroup.getColumnGroups(col,new Vector());
if (v_ret != null) {
return v_ret.elements();
}
}
return null;
}
public void setColumnMargin() {
if (columnGroups == null) return;
int columnMargin = getColumnModel().getColumnMargin();
Enumeration e = columnGroups.elements();
while (e.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)e.nextElement();
cGroup.setColumnMargin(columnMargin);
}
}
}
/*
* (swing1.1beta3)
*
*/
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;
public class GroupableTableHeaderUI extends BasicTableHeaderUI {
public void paint(Graphics g, JComponent c) {
Rectangle clipBounds = g.getClipBounds();
if (header.getColumnModel() == null) return;
((GroupableTableHeader)header).setColumnMargin();
int column = 0;
Dimension size = header.getSize();
Rectangle cellRect = new Rectangle(0, 0, size.width, size.height);
Hashtable h = new Hashtable();
int columnMargin = header.getColumnModel().getColumnMargin();
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
cellRect.height = size.height;
cellRect.y = 0;
TableColumn aColumn = (TableColumn)enumeration.nextElement();
Enumeration cGroups = ((GroupableTableHeader)header).getColumnGroups(aColumn);
if (cGroups != null) {
int groupHeight = 0;
while (cGroups.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)cGroups.nextElement();
Rectangle groupRect = (Rectangle)h.get(cGroup);
if (groupRect == null) {
groupRect = new Rectangle(cellRect);
Dimension d = cGroup.getSize(header.getTable());
groupRect.width = d.width;
groupRect.height = d.height;
h.put(cGroup, groupRect);
}
paintCell(g, groupRect, cGroup);
groupHeight += groupRect.height;
cellRect.height = size.height - groupHeight;
cellRect.y = groupHeight;
}
}
cellRect.width = aColumn.getWidth() + columnMargin;
if (cellRect.intersects(clipBounds)) {
paintCell(g, cellRect, column);
}
cellRect.x += cellRect.width;
column++;
}
}
private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
TableCellRenderer renderer = aColumn.getHeaderRenderer();
//revised by jexp.ru
renderer = new DefaultTableCellRenderer(){
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel header = new JLabel();
header.setForeground(table.getTableHeader().getForeground());
header.setBackground(table.getTableHeader().getBackground());
header.setFont(table.getTableHeader().getFont());
header.setHorizontalAlignment(JLabel.CENTER);
header.setText(value.toString());
header.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return header;
}
};
Component c = renderer.getTableCellRendererComponent(
header.getTable(), aColumn.getHeaderValue(),false, false, -1, columnIndex);
c.setBackground(UIManager.getColor("control"));
rendererPane.add(c);
rendererPane.paintComponent(g, c, header, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
private void paintCell(Graphics g, Rectangle cellRect,ColumnGroup cGroup) {
TableCellRenderer renderer = cGroup.getHeaderRenderer();
//revised by jexp.ru
// if(renderer == null){
// return ;
// }
Component component = renderer.getTableCellRendererComponent(
header.getTable(), cGroup.getHeaderValue(),false, false, -1, -1);
rendererPane.add(component);
rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
private int getHeaderHeight() {
int height = 0;
TableColumnModel columnModel = header.getColumnModel();
for(int column = 0; column < columnModel.getColumnCount(); column++) {
TableColumn aColumn = columnModel.getColumn(column);
TableCellRenderer renderer = aColumn.getHeaderRenderer();
//revised by jexp.ru
if(renderer == null){
return 60;
}
Component comp = renderer.getTableCellRendererComponent(
header.getTable(), aColumn.getHeaderValue(), false, false,-1, column);
int cHeight = comp.getPreferredSize().height;
Enumeration e = ((GroupableTableHeader)header).getColumnGroups(aColumn);
if (e != null) {
while (e.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)e.nextElement();
cHeight += cGroup.getSize(header.getTable()).height;
}
}
height = Math.max(height, cHeight);
}
return height;
}
private Dimension createHeaderSize(long width) {
TableColumnModel columnModel = header.getColumnModel();
width += columnModel.getColumnMargin() * columnModel.getColumnCount();
if (width > Integer.MAX_VALUE) {
width = Integer.MAX_VALUE;
}
return new Dimension((int)width, getHeaderHeight());
}
public Dimension getPreferredSize(JComponent c) {
long width = 0;
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getPreferredWidth();
}
return createHeaderSize(width);
}
}
/*
* (swing1.1beta3)
*
*/
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* ColumnGroup
*
* @version 1.0 10/20/98
* @author Nobuo Tamemasa
*/
class ColumnGroup {
protected TableCellRenderer renderer;
protected Vector v;
protected String text;
protected int margin=0;
public ColumnGroup(String text) {
this(null,text);
}
public ColumnGroup(TableCellRenderer renderer,String text) {
if (renderer == null) {
this.renderer = new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JTableHeader header = table.getTableHeader();
if (header != null) {
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
setHorizontalAlignment(JLabel.CENTER);
setText((value == null) ? "" : value.toString());
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
};
} else {
this.renderer = renderer;
}
this.text = text;
v = new Vector();
}
/**
* @param obj TableColumn or ColumnGroup
*/
public void add(Object obj) {
if (obj == null) { return; }
v.addElement(obj);
}
/**
* @param c TableColumn
* @param v ColumnGroups
*/
public Vector getColumnGroups(TableColumn c, Vector g) {
g.addElement(this);
if (v.contains(c)) return g;
Enumeration e = v.elements();
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof ColumnGroup) {
Vector groups =
(Vector)((ColumnGroup)obj).getColumnGroups(c,(Vector)g.clone());
if (groups != null) return groups;
}
}
return null;
}
public TableCellRenderer getHeaderRenderer() {
return renderer;
}
public void setHeaderRenderer(TableCellRenderer renderer) {
if (renderer != null) {
this.renderer = renderer;
}
}
public Object getHeaderValue() {
return text;
}
public Dimension getSize(JTable table) {
Component comp = renderer.getTableCellRendererComponent(
table, getHeaderValue(), false, false,-1, -1);
int height = comp.getPreferredSize().height;
int width = 0;
Enumeration e = v.elements();
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof TableColumn) {
TableColumn aColumn = (TableColumn)obj;
width += aColumn.getWidth();
width += margin;
} else {
width += ((ColumnGroup)obj).getSize(table).width;
}
}
return new Dimension(width, height);
}
public void setColumnMargin(int margin) {
this.margin = margin;
Enumeration e = v.elements();
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof ColumnGroup) {
((ColumnGroup)obj).setColumnMargin(margin);
}
}
}
}
Hide Column Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1beta2) */
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.SystemColor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Stack;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ScrollPaneLayout;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* @version 1.0 05/31/99
*/
public class HideColumnTableExample extends JFrame {
public HideColumnTableExample() {
super("HideColumnTable Example");
JTable table = new JTable(5, 7);
ColumnButtonScrollPane pane = new ColumnButtonScrollPane(table);
getContentPane().add(pane);
}
public static void main(String[] args) {
HideColumnTableExample frame = new HideColumnTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(400, 100);
frame.setVisible(true);
}
}
class ColumnButtonScrollPane extends JScrollPane {
Component columnButton;
public ColumnButtonScrollPane(JTable table) {
super(table);
TableColumnModel cm = table.getColumnModel();
LimitedTableHeader header = new LimitedTableHeader(cm);
table.setTableHeader(header);
columnButton = createUpperCorner(header);
setCorner(UPPER_RIGHT_CORNER, columnButton);
setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
ColumnButtonScrollPaneLayout layout = new ColumnButtonScrollPaneLayout();
setLayout(layout);
layout.syncWithScrollPane(this);
}
protected Component createUpperCorner(JTableHeader header) {
ColumnButton corner = new ColumnButton(header);
return corner;
}
public class LimitedTableHeader extends JTableHeader {
public LimitedTableHeader(TableColumnModel cm) {
super(cm);
}
// actually, this is a not complete way. but easy one.
// you can see last column painted wider, short time :)
// If you don"t like this kind cheap fake,
// you have to overwrite the paint method in UI class.
public void paintComponent(Graphics g) {
super.paintComponent(g);
columnButton.repaint();
}
}
public class ColumnButton extends JPanel {
JTable table;
TableColumnModel cm;
JButton revealButton;
JButton hideButton;
Stack stack;
public ColumnButton(JTableHeader header) {
setLayout(new GridLayout(1, 2));
setBorder(new LinesBorder(SystemColor.controlShadow, new Insets(0,
1, 0, 0)));
stack = new Stack();
table = header.getTable();
cm = table.getColumnModel();
revealButton = createButton(header, SwingConstants.WEST);
hideButton = createButton(header, SwingConstants.EAST);
add(revealButton);
add(hideButton);
revealButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
TableColumn column = (TableColumn) stack.pop();
cm.addColumn(column);
if (stack.empty()) {
revealButton.setEnabled(false);
}
hideButton.setEnabled(true);
table.sizeColumnsToFit(-1);
}
});
hideButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int n = cm.getColumnCount();
TableColumn column = cm.getColumn(n - 1);
stack.push(column);
cm.removeColumn(column);
if (n < 3) {
hideButton.setEnabled(false);
}
revealButton.setEnabled(true);
table.sizeColumnsToFit(-1);
}
});
if (1 < cm.getColumnCount()) {
hideButton.setEnabled(true);
} else {
hideButton.setEnabled(false);
}
revealButton.setEnabled(false);
}
protected JButton createButton(JTableHeader header, int direction) {
//int iconHeight = header.getPreferredSize().height - 6;
int iconHeight = 8;
JButton button = new JButton();
button.setIcon(new ArrowIcon(iconHeight, direction, true));
button.setDisabledIcon(new ArrowIcon(iconHeight, direction, false));
button.setRequestFocusEnabled(false);
button.setForeground(header.getForeground());
button.setBackground(header.getBackground());
button.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return button;
}
}
}
class ColumnButtonScrollPaneLayout extends ScrollPaneLayout {
public ColumnButtonScrollPaneLayout() {
super.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
}
public void setVerticalScrollBarPolicy(int x) {
// VERTICAL_SCROLLBAR_ALWAYS
super.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_ALWAYS);
}
public void layoutContainer(Container parent) {
super.layoutContainer(parent);
if ((colHead == null) || (!colHead.isVisible()) || (upperRight == null)
|| (vsb == null)) {
return;
}
Rectangle vsbR = new Rectangle(0, 0, 0, 0);
vsbR = vsb.getBounds(vsbR);
Rectangle colHeadR = new Rectangle(0, 0, 0, 0);
colHeadR = colHead.getBounds(colHeadR);
colHeadR.width -= vsbR.width;
colHead.getBounds(colHeadR);
Rectangle upperRightR = upperRight.getBounds();
upperRightR.x -= vsbR.width;
upperRightR.width += vsbR.width + 1;
upperRight.setBounds(upperRightR);
}
}
class LinesBorder extends AbstractBorder implements SwingConstants {
protected int northThickness;
protected int southThickness;
protected int eastThickness;
protected int westThickness;
protected Color northColor;
protected Color southColor;
protected Color eastColor;
protected Color westColor;
public LinesBorder(Color color) {
this(color, 1);
}
public LinesBorder(Color color, int thickness) {
setColor(color);
setThickness(thickness);
}
public LinesBorder(Color color, Insets insets) {
setColor(color);
setThickness(insets);
}
public void paintBorder(Component c, Graphics g, int x, int y, int width,
int height) {
Color oldColor = g.getColor();
g.setColor(northColor);
for (int i = 0; i < northThickness; i++) {
g.drawLine(x, y + i, x + width - 1, y + i);
}
g.setColor(southColor);
for (int i = 0; i < southThickness; i++) {
g
.drawLine(x, y + height - i - 1, x + width - 1, y + height
- i - 1);
}
g.setColor(eastColor);
for (int i = 0; i < westThickness; i++) {
g.drawLine(x + i, y, x + i, y + height - 1);
}
g.setColor(westColor);
for (int i = 0; i < eastThickness; i++) {
g.drawLine(x + width - i - 1, y, x + width - i - 1, y + height - 1);
}
g.setColor(oldColor);
}
public Insets getBorderInsets(Component c) {
return new Insets(northThickness, westThickness, southThickness,
eastThickness);
}
public Insets getBorderInsets(Component c, Insets insets) {
return new Insets(northThickness, westThickness, southThickness,
eastThickness);
}
public boolean isBorderOpaque() {
return true;
}
public void setColor(Color c) {
northColor = c;
southColor = c;
eastColor = c;
westColor = c;
}
public void setColor(Color c, int direction) {
switch (direction) {
case NORTH:
northColor = c;
break;
case SOUTH:
southColor = c;
break;
case EAST:
eastColor = c;
break;
case WEST:
westColor = c;
break;
default:
}
}
public void setThickness(int n) {
northThickness = n;
southThickness = n;
eastThickness = n;
westThickness = n;
}
public void setThickness(Insets insets) {
northThickness = insets.top;
southThickness = insets.bottom;
eastThickness = insets.right;
westThickness = insets.left;
}
public void setThickness(int n, int direction) {
switch (direction) {
case NORTH:
northThickness = n;
break;
case SOUTH:
southThickness = n;
break;
case EAST:
eastThickness = n;
break;
case WEST:
westThickness = n;
break;
default:
}
}
public void append(LinesBorder b, boolean isReplace) {
if (isReplace) {
northThickness = b.northThickness;
southThickness = b.southThickness;
eastThickness = b.eastThickness;
westThickness = b.westThickness;
} else {
northThickness = Math.max(northThickness, b.northThickness);
southThickness = Math.max(southThickness, b.southThickness);
eastThickness = Math.max(eastThickness, b.eastThickness);
westThickness = Math.max(westThickness, b.westThickness);
}
}
public void append(Insets insets, boolean isReplace) {
if (isReplace) {
northThickness = insets.top;
southThickness = insets.bottom;
eastThickness = insets.right;
westThickness = insets.left;
} else {
northThickness = Math.max(northThickness, insets.top);
southThickness = Math.max(southThickness, insets.bottom);
eastThickness = Math.max(eastThickness, insets.right);
westThickness = Math.max(westThickness, insets.left);
}
}
}
class ArrowIcon implements Icon, SwingConstants {
private static final int DEFAULT_SIZE = 11;
//private static final int DEFAULT_SIZE = 5;
private int size;
private int iconSize;
private int direction;
private boolean isEnabled;
private BasicArrowButton iconRenderer;
public ArrowIcon(int direction, boolean isPressedView) {
this(DEFAULT_SIZE, direction, isPressedView);
}
public ArrowIcon(int iconSize, int direction, boolean isEnabled) {
this.size = iconSize / 2;
this.iconSize = iconSize;
this.direction = direction;
this.isEnabled = isEnabled;
iconRenderer = new BasicArrowButton(direction);
}
public void paintIcon(Component c, Graphics g, int x, int y) {
iconRenderer.paintTriangle(g, x, y, size, direction, isEnabled);
}
public int getIconWidth() {
//int retCode;
switch (direction) {
case NORTH:
case SOUTH:
return iconSize;
case EAST:
case WEST:
return size;
}
return iconSize;
}
public int getIconHeight() {
switch (direction) {
case NORTH:
case SOUTH:
return size;
case EAST:
case WEST:
return iconSize;
}
return size;
}
}
Highlight Currency Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class HighlightCurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Highlighted Currency Table");
JTable tbl = new JTable(new CurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tbl.setShowHorizontalLines(false);
tbl.setIntercellSpacing(new Dimension(1, 0));
// Add the stipe renderer.
StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
Color.white, null, null);
// Add the highlight renderer to the last column.
// The following comparator makes it highlight
// cells with negative numeric values.
Comparator cmp = new Comparator() {
public boolean shouldHighlight(JTable tbl, Object value, int row,
int column) {
if (value instanceof Number) {
double columnValue = ((Number) value).doubleValue();
return columnValue < (double) 0.0;
}
return false;
}
};
tcm.getColumn(3).setCellRenderer(
new HighlightRenderer(cmp, null, Color.pink, Color.black,
Color.pink.darker(), Color.white));
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class HighlightRenderer implements TableCellRenderer {
public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
Color backColor, Color foreColor, Color highlightBack,
Color highlightFore) {
this.cmp = cmp;
this.targetRenderer = targetRenderer;
this.backColor = backColor;
this.foreColor = foreColor;
this.highlightBack = highlightBack;
this.highlightFore = highlightFore;
}
public Component getTableCellRendererComponent(JTable tbl, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
}
Component comp = renderer.getTableCellRendererComponent(tbl, value,
isSelected, hasFocus, row, column);
if (isSelected == false && hasFocus == false && value != null) {
if (cmp.shouldHighlight(tbl, value, row, column)) {
comp.setForeground(highlightFore);
comp.setBackground(highlightBack);
} else {
comp.setForeground(foreColor);
comp.setBackground(backColor);
}
}
return comp;
}
protected Comparator cmp;
protected TableCellRenderer targetRenderer;
protected Color backColor;
protected Color foreColor;
protected Color highlightBack;
protected Color highlightFore;
}
interface Comparator {
public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
int column);
}
Highlight Currency Table 2
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class HighlightCurrencyTable2 {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Highlighted Currency Table 2");
JTable tbl = new JTable(new CurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tbl.setShowHorizontalLines(false);
tbl.setIntercellSpacing(new Dimension(1, 0));
// Add the stripe renderer.
StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
Color.white, null, null);
// Add the highlight renderer to the last column.
Comparator cmp = new Comparator() {
public boolean shouldHighlight(JTable tbl, Object value, int row,
int column) {
if (value instanceof Number) {
Object oldValueObj = tbl.getModel().getValueAt(row, 1);
if (oldValueObj instanceof Number) {
double oldValue = ((Number) oldValueObj).doubleValue();
double columnValue = ((Number) value).doubleValue();
return Math.abs(columnValue) > Math.abs(oldValue
/ (double) 10.0);
}
}
return false;
}
};
tcm.getColumn(3).setCellRenderer(
new HighlightRenderer(cmp, null, Color.pink, Color.black,
Color.pink.darker(), Color.white));
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
interface Comparator {
public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
int column);
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class HighlightRenderer implements TableCellRenderer {
public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
Color backColor, Color foreColor, Color highlightBack,
Color highlightFore) {
this.cmp = cmp;
this.targetRenderer = targetRenderer;
this.backColor = backColor;
this.foreColor = foreColor;
this.highlightBack = highlightBack;
this.highlightFore = highlightFore;
}
public Component getTableCellRendererComponent(JTable tbl, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
}
Component comp = renderer.getTableCellRendererComponent(tbl, value,
isSelected, hasFocus, row, column);
if (isSelected == false && hasFocus == false && value != null) {
if (cmp.shouldHighlight(tbl, value, row, column)) {
comp.setForeground(highlightFore);
comp.setBackground(highlightBack);
} else {
comp.setForeground(foreColor);
comp.setBackground(backColor);
}
}
return comp;
}
protected Comparator cmp;
protected TableCellRenderer targetRenderer;
protected Color backColor;
protected Color foreColor;
protected Color highlightBack;
protected Color highlightFore;
}
Icon Currency Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
public class IconCurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Icon Currency Table");
JTable tbl = new JTable(new CurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))),
new Double(0.6213051), new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon)value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
Indicator Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
* @version 1.0 03/03/99
*/
public class IndicatorTableExample extends JPanel {
private static final int MAX = 100;
private static final int MIN = 0;
public IndicatorTableExample() {
setLayout(new BorderLayout());
DefaultTableModel dm = new DefaultTableModel() {
public Class getColumnClass(int col) {
switch (col) {
case 0:
return String.class;
case 1:
return Integer.class;
case 2:
return Integer.class;
default:
return Object.class;
}
}
public boolean isCellEditable(int row, int col) {
switch (col) {
case 2:
return false;
default:
return true;
}
}
public void setValueAt(Object obj, int row, int col) {
if (col != 1) {
super.setValueAt(obj, row, col);
return;
}
try {
Integer integer = new Integer(obj.toString());
super.setValueAt(checkMinMax(integer), row, col);
} catch (NumberFormatException ex) {
ex.printStackTrace();
}
}
};
dm.setDataVector(new Object[][] {
{ "not human", new Integer(100), new Integer(100) },
{ "hard worker", new Integer(76), new Integer(76) },
{ "ordinary guy", new Integer(51), new Integer(51) },
{ "lazy fellow", new Integer(12), new Integer(12) } },
new Object[] { "Name", "Result", "Indicator" });
JTable table = new JTable(dm);
IndicatorCellRenderer renderer = new IndicatorCellRenderer(MIN, MAX);
renderer.setStringPainted(true);
renderer.setBackground(table.getBackground());
// set limit value and fill color
Hashtable limitColors = new Hashtable();
limitColors.put(new Integer(0), Color.green);
limitColors.put(new Integer(60), Color.yellow);
limitColors.put(new Integer(80), Color.red);
renderer.setLimits(limitColors);
table.getColumnModel().getColumn(2).setCellRenderer(renderer);
table.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
if (e.getType() == TableModelEvent.UPDATE) {
int col = e.getColumn();
if (col == 1) {
int row = e.getFirstRow();
TableModel model = (TableModel) e.getSource();
Integer value = (Integer) model.getValueAt(row, col);
model.setValueAt(checkMinMax(value), row, ++col);
}
}
}
});
JScrollPane pane = new JScrollPane(table);
add(pane, BorderLayout.CENTER);
}
public static void main(String[] args) {
JFrame f = new JFrame("IndicatorTable Example");
f.getContentPane()
.add(new IndicatorTableExample(), BorderLayout.CENTER);
f.setSize(400, 120);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
private Integer checkMinMax(Integer value) {
int intValue = value.intValue();
if (intValue < MIN) {
intValue = MIN;
} else if (MAX < intValue) {
intValue = MAX;
}
return new Integer(intValue);
}
}
/**
* @version 1.0 03/03/99
*/
class IndicatorCellRenderer extends JProgressBar implements TableCellRenderer {
private Hashtable limitColors;
private int[] limitValues;
public IndicatorCellRenderer() {
super(JProgressBar.HORIZONTAL);
setBorderPainted(false);
}
public IndicatorCellRenderer(int min, int max) {
super(JProgressBar.HORIZONTAL, min, max);
setBorderPainted(false);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
int n = 0;
if (!(value instanceof Number)) {
String str;
if (value instanceof String) {
str = (String) value;
} else {
str = value.toString();
}
try {
n = Integer.valueOf(str).intValue();
} catch (NumberFormatException ex) {
}
} else {
n = ((Number) value).intValue();
}
Color color = getColor(n);
if (color != null) {
setForeground(color);
}
setValue(n);
return this;
}
public void setLimits(Hashtable limitColors) {
this.limitColors = limitColors;
int i = 0;
int n = limitColors.size();
limitValues = new int[n];
Enumeration e = limitColors.keys();
while (e.hasMoreElements()) {
limitValues[i++] = ((Integer) e.nextElement()).intValue();
}
sort(limitValues);
}
private Color getColor(int value) {
Color color = null;
if (limitValues != null) {
int i;
for (i = 0; i < limitValues.length; i++) {
if (limitValues[i] < value) {
color = (Color) limitColors
.get(new Integer(limitValues[i]));
}
}
}
return color;
}
private void sort(int[] a) {
int n = a.length;
for (int i = 0; i < n - 1; i++) {
int k = i;
for (int j = i + 1; j < n; j++) {
if (a[j] < a[k]) {
k = j;
}
}
int tmp = a[i];
a[i] = a[k];
a[k] = tmp;
}
}
}
JSortTable
package org.tn5250j.gui;
/*
JSortTable.java
Created by Claude Duguay
Copyright (c) 2002
This was taken from a Java Pro magazine article
http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
I have NOT asked for permission to use this.
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Collections;
import java.util.ruparator;
import java.util.Vector;
import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
public class JSortTable extends JTable implements MouseListener {
protected int sortedColumnIndex = -1;
protected boolean sortedColumnAscending = true;
public JSortTable() {
this(new DefaultSortTableModel());
}
public JSortTable(int rows, int cols) {
this(new DefaultSortTableModel(rows, cols));
}
public JSortTable(Object[][] data, Object[] names) {
this(new DefaultSortTableModel(data, names));
}
public JSortTable(Vector data, Vector names) {
this(new DefaultSortTableModel(data, names));
}
public JSortTable(SortTableModel model) {
super(model);
initSortHeader();
}
public JSortTable(SortTableModel model, TableColumnModel colModel) {
super(model, colModel);
initSortHeader();
}
public JSortTable(SortTableModel model, TableColumnModel colModel,
ListSelectionModel selModel) {
super(model, colModel, selModel);
initSortHeader();
}
protected void initSortHeader() {
JTableHeader header = getTableHeader();
header.setDefaultRenderer(new SortHeaderRenderer());
header.addMouseListener(this);
}
public int getSortedColumnIndex() {
return sortedColumnIndex;
}
public boolean isSortedColumnAscending() {
return sortedColumnAscending;
}
public void mouseReleased(MouseEvent event) {
TableColumnModel colModel = getColumnModel();
int index = colModel.getColumnIndexAtX(event.getX());
int modelIndex = colModel.getColumn(index).getModelIndex();
SortTableModel model = (SortTableModel)getModel();
if (model.isSortable(modelIndex)) {
// toggle ascension, if already sorted
if (sortedColumnIndex == index) {
sortedColumnAscending = !sortedColumnAscending;
}
sortedColumnIndex = index;
model.sortColumn(modelIndex, sortedColumnAscending);
}
}
public void mousePressed(MouseEvent event) {}
public void mouseClicked(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
}
/*
DefaultSortTableModel.java
Created by Claude Duguay
Copyright (c) 2002
This was taken from a Java Pro magazine article
http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
I have NOT asked for permission to use this.
*/
class DefaultSortTableModel extends DefaultTableModel
implements SortTableModel {
public DefaultSortTableModel() {}
public DefaultSortTableModel(int rows, int cols) {
super(rows, cols);
}
public DefaultSortTableModel(Object[][] data, Object[] names) {
super(data, names);
}
public DefaultSortTableModel(Object[] names, int rows) {
super(names, rows);
}
public DefaultSortTableModel(Vector names, int rows) {
super(names, rows);
}
public DefaultSortTableModel(Vector data, Vector names) {
super(data, names);
}
public boolean isSortable(int col) {
return true;
}
public void sortColumn(int col, boolean ascending) {
Collections.sort(getDataVector(),
new ColumnComparator(col, ascending));
}
}
/*
SortTableModel.java
Created by Claude Duguay
Copyright (c) 2002
This was taken from a Java Pro magazine article
http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
I have NOT asked for permission to use this.
*/
interface SortTableModel extends TableModel {
public boolean isSortable(int col);
public void sortColumn(int col, boolean ascending);
}
/*
ColumnComparator.java
Created by Claude Duguay
Copyright (c) 2002
This was taken from a Java Pro magazine article
http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
I have NOT asked for permission to use this.
*/
class ColumnComparator implements Comparator {
protected int index;
protected boolean ascending;
public ColumnComparator(int index, boolean ascending) {
this.index = index;
this.ascending = ascending;
}
public int compare(Object one, Object two) {
if (one instanceof Vector && two instanceof Vector) {
Vector vOne = (Vector)one;
Vector vTwo = (Vector)two;
Object oOne = vOne.elementAt(index);
Object oTwo = vTwo.elementAt(index);
if (oOne instanceof Comparable && oTwo instanceof Comparable) {
Comparable cOne = (Comparable)oOne;
Comparable cTwo = (Comparable)oTwo;
if (ascending) {
return cOne.rupareTo(cTwo);
}
else {
return cTwo.rupareTo(cOne);
}
}
}
return 1;
}
}
/*
SortHeaderRenderer.java
Created by Claude Duguay
Copyright (c) 2002
This was taken from a Java Pro magazine article
http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
I have NOT asked for permission to use this.
*/
class SortHeaderRenderer extends DefaultTableCellRenderer {
public static Icon NONSORTED = new SortArrowIcon(SortArrowIcon.NONE);
public static Icon ASCENDING = new SortArrowIcon(SortArrowIcon.ASCENDING);
public static Icon DECENDING = new SortArrowIcon(SortArrowIcon.DECENDING);
public SortHeaderRenderer() {
setHorizontalTextPosition(LEFT);
setHorizontalAlignment(CENTER);
}
public Component getTableCellRendererComponent( JTable table,
Object value,
boolean isSelected,
boolean hasFocus, int row, int col) {
int index = -1;
boolean ascending = true;
if (table instanceof JSortTable) {
JSortTable sortTable = (JSortTable)table;
index = sortTable.getSortedColumnIndex();
ascending = sortTable.isSortedColumnAscending();
}
if (table != null) {
JTableHeader header = table.getTableHeader();
if (header != null) {
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
}
Icon icon = ascending ? ASCENDING : DECENDING;
setIcon(col == index ? icon : NONSORTED);
setText((value == null) ? "" : value.toString());
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
}
/*
SortArrowIcon.java
Created by Claude Duguay
Copyright (c) 2002
This was taken from a Java Pro magazine article
http://www.fawcette.ru/javapro/codepage.asp?loccode=jp0208
I have NOT asked for permission to use this.
*/
class SortArrowIcon implements Icon {
public static final int NONE = 0;
public static final int DECENDING = 1;
public static final int ASCENDING = 2;
protected int direction;
protected int width = 8;
protected int height = 8;
public SortArrowIcon(int direction) {
this.direction = direction;
}
public int getIconWidth() {
return width;
}
public int getIconHeight() {
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
Color bg = c.getBackground();
Color light = bg.brighter();
Color shade = bg.darker();
int w = width;
int h = height;
int m = w / 2;
if (direction == ASCENDING) {
g.setColor(shade);
g.drawLine(x, y, x + w, y);
g.drawLine(x, y, x + m, y + h);
g.setColor(light);
g.drawLine(x + w, y, x + m, y + h);
}
if (direction == DECENDING) {
g.setColor(shade);
g.drawLine(x + m, y, x, y + h);
g.setColor(light);
g.drawLine(x, y + h, x + w, y + h);
g.drawLine(x + m, y, x + w, y + h);
}
}
}
Mixed Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
* (swing1.1beta3)
*/
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
/**
* @version 1.0 11/22/98
*/
public class MixedExample extends JFrame {
public MixedExample() {
super("Mixed Example");
AttributiveCellTableModel ml = new AttributiveCellTableModel(20, 5) {
public Object getValueAt(int row, int col) {
return "" + row + "," + col;
}
};
CellAttribute cellAtt = ml.getCellAttribute();
MultiSpanCellTable table = new MultiSpanCellTable(ml);
table.setCellSelectionEnabled(true);
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setDefaultRenderer(Object.class, new AttributiveCellRenderer());
JScrollPane scroll = new JScrollPane(table);
ColorPanel colorPanel = new ColorPanel(table, (ColoredCell) cellAtt);
FontPanel fontPanel = new FontPanel(table, (CellFont) cellAtt);
SpanPanel spanPanel = new SpanPanel(table, (CellSpan) cellAtt);
Box boxAtt = new Box(BoxLayout.Y_AXIS);
boxAtt.add(colorPanel);
boxAtt.add(fontPanel);
boxAtt.add(spanPanel);
Box box = new Box(BoxLayout.X_AXIS);
box.add(scroll);
box.add(new JSeparator(SwingConstants.HORIZONTAL));
box.add(boxAtt);
getContentPane().add(box);
setSize(400, 300);
setVisible(true);
}
class ColorPanel extends JPanel {
JTable table;
ColoredCell cellAtt;
ColorPanel(final JTable table, final ColoredCell cellAtt) {
this.table = table;
this.cellAtt = cellAtt;
setLayout(new GridLayout(2, 1));
setBorder(BorderFactory.createTitledBorder("Color"));
JButton b_fore = new JButton("Foreground");
b_fore.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeColor(true);
}
});
JButton b_back = new JButton("Background");
b_back.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
changeColor(false);
}
});
JPanel p_buttons = new JPanel();
add(b_fore);
add(b_back);
}
private final void changeColor(boolean isForeground) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
if ((rows == null) || (columns == null))
return;
if ((rows.length < 1) || (columns.length < 1))
return;
Color target = cellAtt.getForeground(rows[0], columns[0]);
Color reference = cellAtt.getBackground(rows[0], columns[0]);
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
for (int j = 0; j < columns.length; j++) {
int column = columns[j];
target = (target != cellAtt.getForeground(row, column)) ? null
: target;
reference = (reference != cellAtt
.getBackground(row, column)) ? null : reference;
}
}
String title;
if (isForeground) {
target = (target != null) ? target : table.getForeground();
reference = (reference != null) ? reference : table
.getBackground();
title = "Foreground Color";
} else {
target = (reference != null) ? reference : table
.getBackground();
reference = (target != null) ? target : table.getForeground();
title = "Foreground Color";
}
TextColorChooser chooser = new TextColorChooser(target, reference,
isForeground);
Color color = chooser.showDialog(MixedExample.this, title);
if (color != null) {
if (isForeground) {
cellAtt.setForeground(color, rows, columns);
} else {
cellAtt.setBackground(color, rows, columns);
}
table.clearSelection();
table.revalidate();
table.repaint();
}
}
}
class FontPanel extends JPanel {
String[] str_size = { "10", "12", "14", "16", "20" };
String[] str_style = { "PLAIN", "BOLD", "ITALIC" };
JComboBox name, style, size;
FontPanel(final JTable table, final CellFont cellAtt) {
setLayout(new BorderLayout());
setBorder(BorderFactory.createTitledBorder("Font"));
Box box = new Box(BoxLayout.X_AXIS);
JPanel p2 = new JPanel(new GridLayout(3, 1));
JPanel p3 = new JPanel(new GridLayout(3, 1));
JPanel p4 = new JPanel(new BorderLayout());
p2.add(new JLabel("Name:"));
p2.add(new JLabel("Style:"));
p2.add(new JLabel("Size:"));
Toolkit toolkit = Toolkit.getDefaultToolkit();
name = new JComboBox(toolkit.getFontList());
style = new JComboBox(str_style);
size = new JComboBox(str_size);
size.setEditable(true);
JButton b_apply = new JButton("Apply");
b_apply.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
if ((rows == null) || (columns == null))
return;
if ((rows.length < 1) || (columns.length < 1))
return;
Font font = new Font((String) name.getSelectedItem(), style
.getSelectedIndex(), Integer.parseInt((String) size
.getSelectedItem()));
cellAtt.setFont(font, rows, columns);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
p3.add(name);
p3.add(style);
p3.add(size);
p4.add(BorderLayout.CENTER, b_apply);
box.add(p2);
box.add(p3);
add(BorderLayout.CENTER, box);
add(BorderLayout.SOUTH, p4);
}
}
class SpanPanel extends JPanel {
JTable table;
CellSpan cellAtt;
SpanPanel(final JTable table, final CellSpan cellAtt) {
this.table = table;
this.cellAtt = cellAtt;
setLayout(new GridLayout(2, 1));
setBorder(BorderFactory.createTitledBorder("Span"));
JButton b_one = new JButton("Combine");
b_one.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
cellAtt.rubine(rows, columns);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
JButton b_split = new JButton("Split");
b_split.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int column = table.getSelectedColumn();
int row = table.getSelectedRow();
cellAtt.split(row, column);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
add(b_one);
add(b_split);
}
}
public static void main(String[] args) {
MixedExample frame = new MixedExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
class AttributiveCellTableModel extends DefaultTableModel {
protected CellAttribute cellAtt;
public AttributiveCellTableModel() {
this((Vector) null, 0);
}
public AttributiveCellTableModel(int numRows, int numColumns) {
Vector names = new Vector(numColumns);
names.setSize(numColumns);
setColumnIdentifiers(names);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, numColumns);
}
public AttributiveCellTableModel(Vector columnNames, int numRows) {
setColumnIdentifiers(columnNames);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
}
public AttributiveCellTableModel(Object[] columnNames, int numRows) {
this(convertToVector(columnNames), numRows);
}
public AttributiveCellTableModel(Vector data, Vector columnNames) {
setDataVector(data, columnNames);
}
public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
public void setDataVector(Vector newData, Vector columnNames) {
if (newData == null)
throw new IllegalArgumentException(
"setDataVector() - Null parameter");
dataVector = new Vector(0);
setColumnIdentifiers(columnNames);
dataVector = newData;
//
cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
.size());
newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public void addColumn(Object columnName, Vector columnData) {
if (columnName == null)
throw new IllegalArgumentException("addColumn() - null parameter");
columnIdentifiers.addElement(columnName);
int index = 0;
Enumeration enumeration = dataVector.elements();
while (enumeration.hasMoreElements()) {
Object value;
if ((columnData != null) && (index < columnData.size()))
value = columnData.elementAt(index);
else
value = null;
((Vector) enumeration.nextElement()).addElement(value);
index++;
}
//
cellAtt.addColumn();
fireTableStructureChanged();
}
public void addRow(Vector rowData) {
Vector newData = null;
if (rowData == null) {
newData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.addElement(newData);
//
cellAtt.addRow();
newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT));
}
public void insertRow(int row, Vector rowData) {
if (rowData == null) {
rowData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.insertElementAt(rowData, row);
//
cellAtt.insertRow(row);
newRowsAdded(new TableModelEvent(this, row, row,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public CellAttribute getCellAttribute() {
return cellAtt;
}
public void setCellAttribute(CellAttribute newCellAtt) {
int numColumns = getColumnCount();
int numRows = getRowCount();
if ((newCellAtt.getSize().width != numColumns)
|| (newCellAtt.getSize().height != numRows)) {
newCellAtt.setSize(new Dimension(numRows, numColumns));
}
cellAtt = newCellAtt;
fireTableDataChanged();
}
/*
* public void changeCellAttribute(int row, int column, Object command) {
* cellAtt.changeAttribute(row, column, command); }
*
* public void changeCellAttribute(int[] rows, int[] columns, Object
* command) { cellAtt.changeAttribute(rows, columns, command); }
*/
}
class DefaultCellAttribute
//implements CellAttribute ,CellSpan {
implements CellAttribute, CellSpan, ColoredCell, CellFont {
//
// !!!! CAUTION !!!!!
// these values must be synchronized to Table data
//
protected int rowSize;
protected int columnSize;
protected int[][][] span; // CellSpan
protected Color[][] foreground; // ColoredCell
protected Color[][] background; //
protected Font[][] font; // CellFont
public DefaultCellAttribute() {
this(1, 1);
}
public DefaultCellAttribute(int numRows, int numColumns) {
setSize(new Dimension(numColumns, numRows));
}
protected void initValue() {
for (int i = 0; i < span.length; i++) {
for (int j = 0; j < span[i].length; j++) {
span[i][j][CellSpan.COLUMN] = 1;
span[i][j][CellSpan.ROW] = 1;
}
}
}
//
// CellSpan
//
public int[] getSpan(int row, int column) {
if (isOutOfBounds(row, column)) {
int[] ret_code = { 1, 1 };
return ret_code;
}
return span[row][column];
}
public void setSpan(int[] span, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.span[row][column] = span;
}
public boolean isVisible(int row, int column) {
if (isOutOfBounds(row, column))
return false;
if ((span[row][column][CellSpan.COLUMN] < 1)
|| (span[row][column][CellSpan.ROW] < 1))
return false;
return true;
}
public void combine(int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
int rowSpan = rows.length;
int columnSpan = columns.length;
int startRow = rows[0];
int startColumn = columns[0];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
|| (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
//System.out.println("can"t combine");
return;
}
}
}
for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
//System.out.println("r " +ii +" c " +jj);
}
}
span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
span[startRow][startColumn][CellSpan.ROW] = rowSpan;
}
public void split(int row, int column) {
if (isOutOfBounds(row, column))
return;
int columnSpan = span[row][column][CellSpan.COLUMN];
int rowSpan = span[row][column][CellSpan.ROW];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
span[row + i][column + j][CellSpan.COLUMN] = 1;
span[row + i][column + j][CellSpan.ROW] = 1;
}
}
}
//
// ColoredCell
//
public Color getForeground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return foreground[row][column];
}
public void setForeground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
foreground[row][column] = color;
}
public void setForeground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(foreground, color, rows, columns);
}
public Color getBackground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return background[row][column];
}
public void setBackground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
background[row][column] = color;
}
public void setBackground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(background, color, rows, columns);
}
//
//
// CellFont
//
public Font getFont(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return font[row][column];
}
public void setFont(Font font, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.font[row][column] = font;
}
public void setFont(Font font, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(this.font, font, rows, columns);
}
//
//
// CellAttribute
//
public void addColumn() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows][numColumns + 1][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numRows; i++) {
span[i][numColumns][CellSpan.COLUMN] = 1;
span[i][numColumns][CellSpan.ROW] = 1;
}
}
public void addRow() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numColumns; i++) {
span[numRows][i][CellSpan.COLUMN] = 1;
span[numRows][i][CellSpan.ROW] = 1;
}
}
public void insertRow(int row) {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
if (0 < row) {
System.arraycopy(oldSpan, 0, span, 0, row - 1);
}
System.arraycopy(oldSpan, 0, span, row, numRows - row);
for (int i = 0; i < numColumns; i++) {
span[row][i][CellSpan.COLUMN] = 1;
span[row][i][CellSpan.ROW] = 1;
}
}
public Dimension getSize() {
return new Dimension(rowSize, columnSize);
}
public void setSize(Dimension size) {
columnSize = size.width;
rowSize = size.height;
span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
foreground = new Color[rowSize][columnSize];
background = new Color[rowSize][columnSize];
font = new Font[rowSize][columnSize];
initValue();
}
/*
* public void changeAttribute(int row, int column, Object command) { }
*
* public void changeAttribute(int[] rows, int[] columns, Object command) { }
*/
protected boolean isOutOfBounds(int row, int column) {
if ((row < 0) || (rowSize <= row) || (column < 0)
|| (columnSize <= column)) {
return true;
}
return false;
}
protected boolean isOutOfBounds(int[] rows, int[] columns) {
for (int i = 0; i < rows.length; i++) {
if ((rows[i] < 0) || (rowSize <= rows[i]))
return true;
}
for (int i = 0; i < columns.length; i++) {
if ((columns[i] < 0) || (columnSize <= columns[i]))
return true;
}
return false;
}
protected void setValues(Object[][] target, Object value, int[] rows,
int[] columns) {
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
for (int j = 0; j < columns.length; j++) {
int column = columns[j];
target[row][column] = value;
}
}
}
}
interface CellAttribute {
public void addColumn();
public void addRow();
public void insertRow(int row);
public Dimension getSize();
public void setSize(Dimension size);
}
interface ColoredCell {
public Color getForeground(int row, int column);
public void setForeground(Color color, int row, int column);
public void setForeground(Color color, int[] rows, int[] columns);
public Color getBackground(int row, int column);
public void setBackground(Color color, int row, int column);
public void setBackground(Color color, int[] rows, int[] columns);
}
interface CellFont {
public Font getFont(int row, int column);
public void setFont(Font font, int row, int column);
public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
public final int ROW = 0;
public final int COLUMN = 1;
public int[] getSpan(int row, int column);
public void setSpan(int[] span, int row, int column);
public boolean isVisible(int row, int column);
public void combine(int[] rows, int[] columns);
public void split(int row, int column);
}
class MultiSpanCellTable extends JTable {
public MultiSpanCellTable(TableModel model) {
super(model);
setUI(new MultiSpanCellTableUI());
getTableHeader().setReorderingAllowed(false);
setCellSelectionEnabled(true);
setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle sRect = super.getCellRect(row, column, includeSpacing);
if ((row < 0) || (column < 0) || (getRowCount() <= row)
|| (getColumnCount() <= column)) {
return sRect;
}
CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
.getCellAttribute();
if (!cellAtt.isVisible(row, column)) {
int temp_row = row;
int temp_column = column;
row += cellAtt.getSpan(temp_row, temp_column)[CellSpan.ROW];
column += cellAtt.getSpan(temp_row, temp_column)[CellSpan.COLUMN];
}
int[] n = cellAtt.getSpan(row, column);
int index = 0;
int columnMargin = getColumnModel().getColumnMargin();
Rectangle cellFrame = new Rectangle();
int aCellHeight = rowHeight + rowMargin;
cellFrame.y = row * aCellHeight;
cellFrame.height = n[CellSpan.ROW] * aCellHeight;
Enumeration enumeration = getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn) enumeration.nextElement();
cellFrame.width = aColumn.getWidth() + columnMargin;
if (index == column)
break;
cellFrame.x += cellFrame.width;
index++;
}
for (int i = 0; i < n[CellSpan.COLUMN] - 1; i++) {
TableColumn aColumn = (TableColumn) enumeration.nextElement();
cellFrame.width += aColumn.getWidth() + columnMargin;
}
if (!includeSpacing) {
Dimension spacing = getIntercellSpacing();
cellFrame.setBounds(cellFrame.x + spacing.width / 2, cellFrame.y
+ spacing.height / 2, cellFrame.width - spacing.width,
cellFrame.height - spacing.height);
}
return cellFrame;
}
private int[] rowColumnAtPoint(Point point) {
int[] retValue = { -1, -1 };
int row = point.y / (rowHeight + rowMargin);
if ((row < 0) || (getRowCount() <= row))
return retValue;
int column = getColumnModel().getColumnIndexAtX(point.x);
CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
.getCellAttribute();
if (cellAtt.isVisible(row, column)) {
retValue[CellSpan.COLUMN] = column;
retValue[CellSpan.ROW] = row;
return retValue;
}
retValue[CellSpan.COLUMN] = column
+ cellAtt.getSpan(row, column)[CellSpan.COLUMN];
retValue[CellSpan.ROW] = row
+ cellAtt.getSpan(row, column)[CellSpan.ROW];
return retValue;
}
public int rowAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.ROW];
}
public int columnAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.COLUMN];
}
public void columnSelectionChanged(ListSelectionEvent e) {
repaint();
}
public void valueChanged(ListSelectionEvent e) {
int firstIndex = e.getFirstIndex();
int lastIndex = e.getLastIndex();
if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
repaint();
}
Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
int numCoumns = getColumnCount();
int index = firstIndex;
for (int i = 0; i < numCoumns; i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
index = lastIndex;
for (int i = 0; i < numCoumns; i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width,
dirtyRegion.height);
}
}
class MultiSpanCellTableUI extends BasicTableUI {
public void paint(Graphics g, JComponent c) {
Rectangle oldClipBounds = g.getClipBounds();
Rectangle clipBounds = new Rectangle(oldClipBounds);
int tableWidth = table.getColumnModel().getTotalColumnWidth();
clipBounds.width = Math.min(clipBounds.width, tableWidth);
g.setClip(clipBounds);
int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
int lastIndex = table.getRowCount() - 1;
Rectangle rowRect = new Rectangle(0, 0, tableWidth, table
.getRowHeight()
+ table.getRowMargin());
rowRect.y = firstIndex * rowRect.height;
for (int index = firstIndex; index <= lastIndex; index++) {
if (rowRect.intersects(clipBounds)) {
//System.out.println(); // debug
//System.out.print("" + index +": "); // row
paintRow(g, index);
}
rowRect.y += rowRect.height;
}
g.setClip(oldClipBounds);
}
private void paintRow(Graphics g, int row) {
Rectangle rect = g.getClipBounds();
boolean drawn = false;
AttributiveCellTableModel tableModel = (AttributiveCellTableModel) table
.getModel();
CellSpan cellAtt = (CellSpan) tableModel.getCellAttribute();
int numColumns = table.getColumnCount();
for (int column = 0; column < numColumns; column++) {
Rectangle cellRect = table.getCellRect(row, column, true);
int cellRow, cellColumn;
if (cellAtt.isVisible(row, column)) {
cellRow = row;
cellColumn = column;
// System.out.print(" "+column+" "); // debug
} else {
cellRow = row + cellAtt.getSpan(row, column)[CellSpan.ROW];
cellColumn = column
+ cellAtt.getSpan(row, column)[CellSpan.COLUMN];
// System.out.print(" ("+column+")"); // debug
}
if (cellRect.intersects(rect)) {
drawn = true;
paintCell(g, cellRect, cellRow, cellColumn);
} else {
if (drawn)
break;
}
}
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
int spacingHeight = table.getRowMargin();
int spacingWidth = table.getColumnModel().getColumnMargin();
Color c = g.getColor();
g.setColor(table.getGridColor());
g.drawRect(cellRect.x, cellRect.y, cellRect.width - 1,
cellRect.height - 1);
g.setColor(c);
cellRect.setBounds(cellRect.x + spacingWidth / 2, cellRect.y
+ spacingHeight / 2, cellRect.width - spacingWidth,
cellRect.height - spacingHeight);
if (table.isEditing() && table.getEditingRow() == row
&& table.getEditingColumn() == column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
} else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if (component.getParent() == null) {
rendererPane.add(component);
}
rendererPane.paintComponent(g, component, table, cellRect.x,
cellRect.y, cellRect.width, cellRect.height, true);
}
}
}
class AttributiveCellRenderer extends JLabel implements TableCellRenderer {
protected static Border noFocusBorder;
public AttributiveCellRenderer() {
noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setOpaque(true);
setBorder(noFocusBorder);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Color foreground = null;
Color background = null;
Font font = null;
TableModel model = table.getModel();
if (model instanceof AttributiveCellTableModel) {
CellAttribute cellAtt = ((AttributiveCellTableModel) model)
.getCellAttribute();
if (cellAtt instanceof ColoredCell) {
foreground = ((ColoredCell) cellAtt).getForeground(row, column);
background = ((ColoredCell) cellAtt).getBackground(row, column);
}
if (cellAtt instanceof CellFont) {
font = ((CellFont) cellAtt).getFont(row, column);
}
}
if (isSelected) {
setForeground((foreground != null) ? foreground : table
.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground((foreground != null) ? foreground : table
.getForeground());
setBackground((background != null) ? background : table
.getBackground());
}
setFont((font != null) ? font : table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground((foreground != null) ? foreground : UIManager
.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(noFocusBorder);
}
setValue(value);
return this;
}
protected void setValue(Object value) {
setText((value == null) ? "" : value.toString());
}
}
class TextPreviewLabel extends JLabel {
private String sampleText = " Sample Text Sample Text ";
boolean isForgroundSelection;
public TextPreviewLabel() {
this(Color.black, Color.white, true);
}
public TextPreviewLabel(Color fore, Color back, boolean isForgroundSelection) {
setOpaque(true);
setForeground(fore);
setBackground(back);
this.isForgroundSelection = isForgroundSelection;
setText(sampleText);
}
public void setForeground(Color col) {
if (isForgroundSelection) {
super.setForeground(col);
} else {
super.setBackground(col);
}
}
}
class ColorChooserDialog extends JDialog {
private Color initialColor;
private Color retColor;
private JColorChooser chooserPane;
public ColorChooserDialog(Component c, String title,
final JColorChooser chooserPane) {
super(JOptionPane.getFrameForComponent(c), title, true);
setResizable(false);
this.chooserPane = chooserPane;
String okString = UIManager.getString("ColorChooser.okText");
String cancelString = UIManager.getString("ColorChooser.cancelText");
String resetString = UIManager.getString("ColorChooser.resetText");
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(chooserPane, BorderLayout.CENTER);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
JButton okButton = new JButton(okString);
getRootPane().setDefaultButton(okButton);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
retColor = chooserPane.getColor();
setVisible(false);
}
});
buttonPane.add(okButton);
JButton cancelButton = new JButton(cancelString);
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
retColor = null;
setVisible(false);
}
});
buttonPane.add(cancelButton);
JButton resetButton = new JButton(resetString);
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
chooserPane.setColor(initialColor);
}
});
buttonPane.add(resetButton);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(c);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
}
});
}
public Color getColor() {
return retColor;
}
}
class TextColorChooser extends JColorChooser {
public TextColorChooser(Color target, Color reference,
boolean isForgroundSelection) {
super(target);
if (isForgroundSelection) {
setPreviewPanel(new TextPreviewLabel(target, reference,
isForgroundSelection));
} else {
setPreviewPanel(new TextPreviewLabel(reference, target,
isForgroundSelection));
}
updateUI();
}
public Color showDialog(Component component, String title) {
ColorChooserDialog dialog = new ColorChooserDialog(component, title,
this);
dialog.show();
Color col = dialog.getColor();
dialog.dispose();
return col;
}
}
MultiLine Cell Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
* If You can accept all cells have same Height.
*/
/* (swing1.1beta3) */
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
* @version 1.0 11/09/98
*/
public class MultiLineCellExample extends JFrame {
MultiLineCellExample() {
super("Multi-Line Cell Example");
DefaultTableModel dm = new DefaultTableModel() {
public Class getColumnClass(int columnIndex) {
return String.class;
}
};
dm.setDataVector(new Object[][] { { "a\na", "b\nb", "c\nc" },
{ "A\nA", "B\nB", "C\nC" } }, new Object[] { "1", "2", "3" });
JTable table = new JTable(dm);
int lines = 2;
table.setRowHeight(table.getRowHeight() * lines);
//
// table.setRowHeight(0);
//
// I got "java.lang.IllegalArgumentException: New row height less than
// 1"
//
table.setDefaultRenderer(String.class, new MultiLineCellRenderer());
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
setSize(400, 130);
setVisible(true);
}
public static void main(String[] args) {
MultiLineCellExample frame = new MultiLineCellExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/**
* @version 1.0 11/09/98
*/
class MultiLineCellRenderer extends JTextArea implements TableCellRenderer {
public MultiLineCellRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setFont(table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground(UIManager.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(new EmptyBorder(1, 2, 1, 2));
}
setText((value == null) ? "" : value.toString());
return this;
}
}
MultiLine Header Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
/**
* @version 1.0 11/09/98
*/
public class MultiLineHeaderExample extends JFrame {
MultiLineHeaderExample() {
super("Multi-Line Header Example");
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(
new Object[][] { { "a", "b", "c" }, { "A", "B", "C" } },
new Object[] { "1st\nalpha", "2nd\nbeta", "3rd\ngamma" });
JTable table = new JTable(dm);
MultiLineHeaderRenderer renderer = new MultiLineHeaderRenderer();
Enumeration e = table.getColumnModel().getColumns();
while (e.hasMoreElements()) {
((TableColumn) e.nextElement()).setHeaderRenderer(renderer);
}
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
setSize(400, 110);
setVisible(true);
}
public static void main(String[] args) {
MultiLineHeaderExample frame = new MultiLineHeaderExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/**
* @version 1.0 11/09/98
*/
class MultiLineHeaderRenderer extends JList implements TableCellRenderer {
public MultiLineHeaderRenderer() {
setOpaque(true);
setForeground(UIManager.getColor("TableHeader.foreground"));
setBackground(UIManager.getColor("TableHeader.background"));
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
ListCellRenderer renderer = getCellRenderer();
((JLabel) renderer).setHorizontalAlignment(JLabel.CENTER);
setCellRenderer(renderer);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
setFont(table.getFont());
String str = (value == null) ? "" : value.toString();
BufferedReader br = new BufferedReader(new StringReader(str));
String line;
Vector v = new Vector();
try {
while ((line = br.readLine()) != null) {
v.addElement(line);
}
} catch (IOException ex) {
ex.printStackTrace();
}
setListData(v);
return this;
}
}
MultiLine Header Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
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.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class MultiLineHeaderTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Multi-line Header Table");
JTable tbl = new JTable(new CurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tcm.getColumn(1).setPreferredWidth(100);
tcm.getColumn(1).setMinWidth(100);
// Add the stripe renderer.
StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
Color.white, null, null);
// Add the custom header renderer
MultiLineHeaderRenderer headerRenderer = new MultiLineHeaderRenderer(
SwingConstants.CENTER, SwingConstants.BOTTOM);
headerRenderer.setBackground(Color.blue);
headerRenderer.setForeground(Color.white);
headerRenderer.setFont(new Font("Dialog", Font.BOLD, 12));
int columns = tableHeaders.length;
for (int i = 0; i < columns; i++) {
tcm.getColumn(i).setHeaderRenderer(headerRenderer);
tcm.getColumn(i).setHeaderValue(tableHeaders[i]);
}
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
// Header values. Note the table model provides
// string column names that are the default header
// values.
public static Object[][] tableHeaders = new Object[][] {
new String[] { "Currency" },
new String[] { "Yesterday"s", "Rate" },
new String[] { "Today"s", "Rate" },
new String[] { "Rate", "Change" } };
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class MultiLineHeaderRenderer extends JPanel implements TableCellRenderer {
public MultiLineHeaderRenderer(int horizontalAlignment,
int verticalAlignment) {
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
switch (horizontalAlignment) {
case SwingConstants.LEFT:
alignmentX = (float) 0.0;
break;
case SwingConstants.CENTER:
alignmentX = (float) 0.5;
break;
case SwingConstants.RIGHT:
alignmentX = (float) 1.0;
break;
default:
throw new IllegalArgumentException(
"Illegal horizontal alignment value");
}
setBorder(headerBorder);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setOpaque(true);
background = null;
}
public void setForeground(Color foreground) {
this.foreground = foreground;
super.setForeground(foreground);
}
public void setBackground(Color background) {
this.background = background;
super.setBackground(background);
}
public void setFont(Font font) {
this.font = font;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
removeAll();
invalidate();
if (value == null) {
// Do nothing if no value
return this;
}
// Set the foreground and background colors
// from the table header if they are not set
if (table != null) {
JTableHeader header = table.getTableHeader();
if (header != null) {
if (foreground == null) {
super.setForeground(header.getForeground());
}
if (background == null) {
super.setBackground(header.getBackground());
}
}
}
if (verticalAlignment != SwingConstants.TOP) {
add(Box.createVerticalGlue());
}
Object[] values;
int length;
if (value instanceof Object[]) {
// Input is an array - use it
values = (Object[]) value;
} else {
// Not an array - turn it into one
values = new Object[1];
values[0] = value;
}
length = values.length;
// Configure each row of the header using
// a separate JLabel. If a given row is
// a JComponent, add it directly..
for (int i = 0; i < length; i++) {
Object thisRow = values[i];
if (thisRow instanceof JComponent) {
add((JComponent) thisRow);
} else {
JLabel l = new JLabel();
setValue(l, thisRow, i);
add(l);
}
}
if (verticalAlignment != SwingConstants.BOTTOM) {
add(Box.createVerticalGlue());
}
return this;
}
// Configures a label for one line of the header.
// This can be overridden by derived classes
protected void setValue(JLabel l, Object value, int lineNumber) {
if (value != null && value instanceof Icon) {
l.setIcon((Icon) value);
} else {
l.setText(value == null ? "" : value.toString());
}
l.setHorizontalAlignment(horizontalAlignment);
l.setAlignmentX(alignmentX);
l.setOpaque(false);
l.setForeground(foreground);
l.setFont(font);
}
protected int verticalAlignment;
protected int horizontalAlignment;
protected float alignmentX;
// These attributes may be explicitly set
// They are defaulted to the colors and attributes
// of the table header
protected Color foreground;
protected Color background;
// These attributes have fixed defaults
protected Border headerBorder = UIManager
.getBorder("TableHeader.cellBorder");
protected Font font = UIManager.getFont("TableHeader.font");
}
MultiLine Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
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.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class MultiLineTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Multi-line Cell Table");
JTable tbl = new JTable(new MultiLineTableModel());
// Create the custom cell renderer
MultiLineCellRenderer multiLineRenderer = new MultiLineCellRenderer(
SwingConstants.LEFT, SwingConstants.CENTER);
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(75);
tcm.getColumn(0).setMinWidth(75);
tcm.getColumn(1).setPreferredWidth(150);
tcm.getColumn(1).setMinWidth(150);
// Install the multi-line renderer
tcm.getColumn(0).setCellRenderer(multiLineRenderer);
tcm.getColumn(1).setCellRenderer(multiLineRenderer);
// Set the table row height
tbl.setRowHeight(56);
// Add the stripe renderer.
StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
Color.white, null, null);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class MultiLineTableModel extends AbstractTableModel {
protected String[] columnNames = { "Flight", "Crew" };
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return 2;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected Object[][] data = new Object[][] {
{
"Apollo 11",
new String[] { "Neil Armstrong", "Buzz Aldrin",
"Michael Collins" } },
{
"Apollo 12",
new String[] { "Pete Conrad", "Alan Bean", "Richard Gordon" } },
{
"Apollo 13",
new String[] { "James Lovell", "Fred Haise", "Jack Swigert" } },
{
"Apollo 14",
new String[] { "Alan Shepard", "Edgar Mitchell",
"Stuart Roosa" } },
{ "Apollo 15",
new String[] { "Dave Scott", "Jim Irwin", "Al Worden" } },
{
"Apollo 16",
new String[] { "John Young", "Charlie Duke",
"Ken Mattingly" } },
{
"Apollo 17",
new String[] { "Eugene Cernan", "Harrison Schmitt",
"Ron Evans" } } };
}
class MultiLineCellRenderer extends JPanel implements TableCellRenderer {
public MultiLineCellRenderer(int horizontalAlignment, int verticalAlignment) {
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
switch (horizontalAlignment) {
case SwingConstants.LEFT:
alignmentX = (float) 0.0;
break;
case SwingConstants.CENTER:
alignmentX = (float) 0.5;
break;
case SwingConstants.RIGHT:
alignmentX = (float) 1.0;
break;
default:
throw new IllegalArgumentException(
"Illegal horizontal alignment value");
}
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setOpaque(true);
setBorder(border);
background = null;
foreground = null;
}
public void setForeground(Color foreground) {
super.setForeground(foreground);
Component[] comps = this.getComponents();
int ncomp = comps.length;
for (int i = 0; i < ncomp; i++) {
Component comp = comps[i];
if (comp instanceof JLabel) {
comp.setForeground(foreground);
}
}
}
public void setBackground(Color background) {
this.background = background;
super.setBackground(background);
}
public void setFont(Font font) {
this.font = font;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
removeAll();
invalidate();
if (value == null || table == null) {
// Do nothing if no value
return this;
}
Color cellForeground;
Color cellBackground;
// Set the foreground and background colors
// from the table if they are not set
cellForeground = (foreground == null ? table.getForeground()
: foreground);
cellBackground = (background == null ? table.getBackground()
: background);
// Handle selection and focus colors
if (isSelected == true) {
cellForeground = table.getSelectionForeground();
cellBackground = table.getSelectionBackground();
}
if (hasFocus == true) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
cellForeground = UIManager
.getColor("Table.focusCellForeground");
cellBackground = UIManager
.getColor("Table.focusCellBackground");
}
} else {
setBorder(border);
}
super.setForeground(cellForeground);
super.setBackground(cellBackground);
// Default the font from the table
if (font == null) {
font = table.getFont();
}
if (verticalAlignment != SwingConstants.TOP) {
add(Box.createVerticalGlue());
}
Object[] values;
int length;
if (value instanceof Object[]) {
// Input is an array - use it
values = (Object[]) value;
} else {
// Not an array - turn it into one
values = new Object[1];
values[0] = value;
}
length = values.length;
// Configure each row of the cell using
// a separate JLabel. If a given row is
// a JComponent, add it directly..
for (int i = 0; i < length; i++) {
Object thisRow = values[i];
if (thisRow instanceof JComponent) {
add((JComponent) thisRow);
} else {
JLabel l = new JLabel();
setValue(l, thisRow, i, cellForeground);
add(l);
}
}
if (verticalAlignment != SwingConstants.BOTTOM) {
add(Box.createVerticalGlue());
}
return this;
}
// Configures a label for one line of the cell.
// This can be overridden by derived classes
protected void setValue(JLabel l, Object value, int lineNumber,
Color cellForeground) {
if (value != null && value instanceof Icon) {
l.setIcon((Icon) value);
} else {
l.setText(value == null ? "" : value.toString());
}
l.setHorizontalAlignment(horizontalAlignment);
l.setAlignmentX(alignmentX);
l.setOpaque(false);
l.setForeground(cellForeground);
l.setFont(font);
}
protected int verticalAlignment;
protected int horizontalAlignment;
protected float alignmentX;
// These attributes may be explicitly set
// They are defaulted to the colors and attributes
// of the table
protected Color foreground;
protected Color background;
protected Font font;
protected static Border border = new EmptyBorder(1, 2, 1, 2);
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
multiple Component Table 2: checkbox
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.ruponent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import java.util.Hashtable;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
/**
* @version 1.0 11/09/98
*/
class CheckBoxRenderer extends JCheckBox implements TableCellRenderer {
CheckBoxRenderer() {
setHorizontalAlignment(JLabel.CENTER);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
//super.setBackground(table.getSelectionBackground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setSelected((value != null && ((Boolean) value).booleanValue()));
return this;
}
}
public class MultiComponentTable2 extends JFrame {
public MultiComponentTable2() {
super("MultiComponent Table");
DefaultTableModel dm = new DefaultTableModel() {
public boolean isCellEditable(int row, int column) {
if (column == 0) {
return true;
}
return false;
}
};
dm.setDataVector(new Object[][] {
{ "true", "String", "JLabel", "JComboBox" },
{ "false", "String", "JLabel", "JComboBox" },
{ new Boolean(true), "Boolean", "JCheckBox", "JCheckBox" },
{ new Boolean(false), "Boolean", "JCheckBox", "JCheckBox" },
{ "true", "String", "JLabel", "JTextField" },
{ "false", "String", "JLabel", "JTextField" } }, new Object[] {
"Component", "Data", "Renderer", "Editor" });
CheckBoxRenderer checkBoxRenderer = new CheckBoxRenderer();
EachRowRenderer rowRenderer = new EachRowRenderer();
rowRenderer.add(2, checkBoxRenderer);
rowRenderer.add(3, checkBoxRenderer);
JComboBox comboBox = new JComboBox();
comboBox.addItem("true");
comboBox.addItem("false");
JCheckBox checkBox = new JCheckBox();
checkBox.setHorizontalAlignment(JLabel.CENTER);
DefaultCellEditor comboBoxEditor = new DefaultCellEditor(comboBox);
DefaultCellEditor checkBoxEditor = new DefaultCellEditor(checkBox);
JTable table = new JTable(dm);
// modified by jexp.ru
EachRowEditor rowEditor = new EachRowEditor(table);
rowEditor.setEditorAt(0, comboBoxEditor);
rowEditor.setEditorAt(1, comboBoxEditor);
rowEditor.setEditorAt(2, checkBoxEditor);
rowEditor.setEditorAt(3, checkBoxEditor);
// end
table.getColumn("Component").setCellRenderer(rowRenderer);
table.getColumn("Component").setCellEditor(rowEditor);
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
setSize(400, 160);
setVisible(true);
}
public static void main(String[] args) {
MultiComponentTable2 frame = new MultiComponentTable2();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/**
* @version 1.0 11/09/98
*/
class EachRowRenderer implements TableCellRenderer {
protected Hashtable renderers;
protected TableCellRenderer renderer, defaultRenderer;
public EachRowRenderer() {
renderers = new Hashtable();
defaultRenderer = new DefaultTableCellRenderer();
}
public void add(int row, TableCellRenderer renderer) {
renderers.put(new Integer(row), renderer);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
renderer = (TableCellRenderer) renderers.get(new Integer(row));
if (renderer == null) {
renderer = defaultRenderer;
}
return renderer.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
}
}
/**
* each row TableCellEditor
*
* @version 1.1 09/09/99
* @author Nobuo Tamemasa
*/
class EachRowEditor implements TableCellEditor {
protected Hashtable editors;
protected TableCellEditor editor, defaultEditor;
JTable table;
/**
* Constructs a EachRowEditor. create default editor
*
* @see TableCellEditor
* @see DefaultCellEditor
*/
public EachRowEditor(JTable table) {
this.table = table;
editors = new Hashtable();
defaultEditor = new DefaultCellEditor(new JTextField());
}
/**
* @param row
* table row
* @param editor
* table cell editor
*/
public void setEditorAt(int row, TableCellEditor editor) {
editors.put(new Integer(row), editor);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//editor = (TableCellEditor)editors.get(new Integer(row));
//if (editor == null) {
// editor = defaultEditor;
//}
return editor.getTableCellEditorComponent(table, value, isSelected,
row, column);
}
public Object getCellEditorValue() {
return editor.getCellEditorValue();
}
public boolean stopCellEditing() {
return editor.stopCellEditing();
}
public void cancelCellEditing() {
editor.cancelCellEditing();
}
public boolean isCellEditable(EventObject anEvent) {
selectEditor((MouseEvent) anEvent);
return editor.isCellEditable(anEvent);
}
public void addCellEditorListener(CellEditorListener l) {
editor.addCellEditorListener(l);
}
public void removeCellEditorListener(CellEditorListener l) {
editor.removeCellEditorListener(l);
}
public boolean shouldSelectCell(EventObject anEvent) {
selectEditor((MouseEvent) anEvent);
return editor.shouldSelectCell(anEvent);
}
protected void selectEditor(MouseEvent e) {
int row;
if (e == null) {
row = table.getSelectionModel().getAnchorSelectionIndex();
} else {
row = table.rowAtPoint(e.getPoint());
}
editor = (TableCellEditor) editors.get(new Integer(row));
if (editor == null) {
editor = defaultEditor;
}
}
}
Multiple Component Table: Checkbox and Combobox
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
/**
* @version 1.0 11/09/98
*/
class ComboString {
String str;
ComboString(String str) {
this.str = str;
}
public String toString() {
return str;
}
}
class MultiRenderer extends DefaultTableCellRenderer {
JCheckBox checkBox = new JCheckBox();
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof Boolean) { // Boolean
checkBox.setSelected(((Boolean) value).booleanValue());
checkBox.setHorizontalAlignment(JLabel.CENTER);
return checkBox;
}
String str = (value == null) ? "" : value.toString();
return super.getTableCellRendererComponent(table, str, isSelected,
hasFocus, row, column);
}
}
class MultiEditor implements TableCellEditor {
private final static int COMBO = 0;
private final static int BOOLEAN = 1;
private final static int STRING = 2;
private final static int NUM_EDITOR = 3;
DefaultCellEditor[] cellEditors;
JComboBox comboBox;
int flg;
public MultiEditor() {
cellEditors = new DefaultCellEditor[NUM_EDITOR];
comboBox = new JComboBox();
comboBox.addItem("true");
comboBox.addItem("false");
cellEditors[COMBO] = new DefaultCellEditor(comboBox);
JCheckBox checkBox = new JCheckBox();
//checkBox.setOpaque( true );
checkBox.setHorizontalAlignment(JLabel.CENTER);
cellEditors[BOOLEAN] = new DefaultCellEditor(checkBox);
JTextField textField = new JTextField();
cellEditors[STRING] = new DefaultCellEditor(textField);
flg = NUM_EDITOR; // nobody
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value instanceof ComboString) { // ComboString
flg = COMBO;
String str = (value == null) ? "" : value.toString();
return cellEditors[COMBO].getTableCellEditorComponent(table, str,
isSelected, row, column);
} else if (value instanceof Boolean) { // Boolean
flg = BOOLEAN;
return cellEditors[BOOLEAN].getTableCellEditorComponent(table,
value, isSelected, row, column);
} else if (value instanceof String) { // String
flg = STRING;
return cellEditors[STRING].getTableCellEditorComponent(table,
value, isSelected, row, column);
}
return null;
}
public Object getCellEditorValue() {
switch (flg) {
case COMBO:
String str = (String) comboBox.getSelectedItem();
return new ComboString(str);
case BOOLEAN:
case STRING:
return cellEditors[flg].getCellEditorValue();
default:
return null;
}
}
public Component getComponent() {
return cellEditors[flg].getComponent();
}
public boolean stopCellEditing() {
return cellEditors[flg].stopCellEditing();
}
public void cancelCellEditing() {
cellEditors[flg].cancelCellEditing();
}
public boolean isCellEditable(EventObject anEvent) {
return cellEditors[flg].isCellEditable(anEvent);
}
public boolean shouldSelectCell(EventObject anEvent) {
return cellEditors[flg].shouldSelectCell(anEvent);
}
public void addCellEditorListener(CellEditorListener l) {
cellEditors[flg].addCellEditorListener(l);
}
public void removeCellEditorListener(CellEditorListener l) {
cellEditors[flg].removeCellEditorListener(l);
}
public void setClickCountToStart(int n) {
cellEditors[flg].setClickCountToStart(n);
}
public int getClickCountToStart() {
return cellEditors[flg].getClickCountToStart();
}
}
public class MultiComponentTable extends JFrame {
public MultiComponentTable() {
super("MultiComponent Table");
DefaultTableModel dm = new DefaultTableModel() {
public boolean isCellEditable(int row, int column) {
if (column == 0) {
return true;
}
return false;
}
};
dm.setDataVector(
new Object[][] {
{ new ComboString("true"), "ComboString", "JLabel",
"JComboBox" },
{ new ComboString("false"), "ComboString", "JLabel",
"JComboBox" },
{ new Boolean(true), "Boolean", "JCheckBox",
"JCheckBox" },
{ new Boolean(false), "Boolean", "JCheckBox",
"JCheckBox" },
{ "true", "String", "JLabel", "JTextField" },
{ "false", "String", "JLabel", "JTextField" } },
new Object[] { "Component", "Data", "Renderer", "Editor" });
JTable table = new JTable(dm);
table.getColumn("Component").setCellRenderer(new MultiRenderer());
table.getColumn("Component").setCellEditor(new MultiEditor());
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
setSize(400, 160);
setVisible(true);
}
public static void main(String[] args) {
MultiComponentTable frame = new MultiComponentTable();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
multiple Font Cell Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
/**
* @version 1.0 11/22/98
*/
public class MultiFontCellTableExample extends JFrame {
public MultiFontCellTableExample() {
super("Multi-Font Cell Example");
AttributiveCellTableModel ml = new AttributiveCellTableModel(8, 3);
CellFont cellAtt = (CellFont) ml.getCellAttribute();
JTable table = new JTable(ml);
table.setRowHeight(26);
table.setCellSelectionEnabled(true);
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
table.setDefaultRenderer(Object.class, new AttributiveCellRenderer());
JScrollPane scroll = new JScrollPane(table);
FontPanel fontPanel = new FontPanel(table, cellAtt);
Box box = new Box(BoxLayout.X_AXIS);
box.add(scroll);
box.add(new JSeparator(SwingConstants.HORIZONTAL));
box.add(fontPanel);
getContentPane().add(box);
setSize(400, 200);
setVisible(true);
}
class FontPanel extends JPanel {
String[] str_size = { "10", "12", "14", "16", "20", "24" };
String[] str_style = { "PLAIN", "BOLD", "ITALIC" };
JComboBox name, style, size;
FontPanel(final JTable table, final CellFont cellAtt) {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
Box box = new Box(BoxLayout.X_AXIS);
JPanel p2 = new JPanel(new GridLayout(3, 1));
JPanel p3 = new JPanel(new GridLayout(3, 1));
JPanel p4 = new JPanel(new FlowLayout());
p2.add(new JLabel("Name:"));
p2.add(new JLabel("Style:"));
p2.add(new JLabel("Size:"));
Toolkit toolkit = Toolkit.getDefaultToolkit();
name = new JComboBox(toolkit.getFontList());
style = new JComboBox(str_style);
size = new JComboBox(str_size);
size.setEditable(true);
JButton b_apply = new JButton("Apply");
b_apply.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
if ((rows == null) || (columns == null))
return;
if ((rows.length < 1) || (columns.length < 1))
return;
Font font = new Font((String) name.getSelectedItem(), style
.getSelectedIndex(), Integer.parseInt((String) size
.getSelectedItem()));
cellAtt.setFont(font, rows, columns);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
p3.add(name);
p3.add(style);
p3.add(size);
p4.add(b_apply);
box.add(p2);
box.add(p3);
add(box);
add(p4);
}
}
public static void main(String[] args) {
MultiFontCellTableExample frame = new MultiFontCellTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/**
* @version 1.0 11/22/98
*/
class AttributiveCellTableModel extends DefaultTableModel {
protected CellAttribute cellAtt;
public AttributiveCellTableModel() {
this((Vector) null, 0);
}
public AttributiveCellTableModel(int numRows, int numColumns) {
Vector names = new Vector(numColumns);
names.setSize(numColumns);
setColumnIdentifiers(names);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, numColumns);
}
public AttributiveCellTableModel(Vector columnNames, int numRows) {
setColumnIdentifiers(columnNames);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
}
public AttributiveCellTableModel(Object[] columnNames, int numRows) {
this(convertToVector(columnNames), numRows);
}
public AttributiveCellTableModel(Vector data, Vector columnNames) {
setDataVector(data, columnNames);
}
public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
public void setDataVector(Vector newData, Vector columnNames) {
if (newData == null)
throw new IllegalArgumentException(
"setDataVector() - Null parameter");
dataVector = new Vector(0);
setColumnIdentifiers(columnNames);
dataVector = newData;
//
cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
.size());
newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public void addColumn(Object columnName, Vector columnData) {
if (columnName == null)
throw new IllegalArgumentException("addColumn() - null parameter");
columnIdentifiers.addElement(columnName);
int index = 0;
Enumeration eeration = dataVector.elements();
while (eeration.hasMoreElements()) {
Object value;
if ((columnData != null) && (index < columnData.size()))
value = columnData.elementAt(index);
else
value = null;
((Vector) eeration.nextElement()).addElement(value);
index++;
}
//
cellAtt.addColumn();
fireTableStructureChanged();
}
public void addRow(Vector rowData) {
Vector newData = null;
if (rowData == null) {
newData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.addElement(newData);
//
cellAtt.addRow();
newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT));
}
public void insertRow(int row, Vector rowData) {
if (rowData == null) {
rowData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.insertElementAt(rowData, row);
//
cellAtt.insertRow(row);
newRowsAdded(new TableModelEvent(this, row, row,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public CellAttribute getCellAttribute() {
return cellAtt;
}
public void setCellAttribute(CellAttribute newCellAtt) {
int numColumns = getColumnCount();
int numRows = getRowCount();
if ((newCellAtt.getSize().width != numColumns)
|| (newCellAtt.getSize().height != numRows)) {
newCellAtt.setSize(new Dimension(numRows, numColumns));
}
cellAtt = newCellAtt;
fireTableDataChanged();
}
/*
* public void changeCellAttribute(int row, int column, Object command) {
* cellAtt.changeAttribute(row, column, command); }
*
* public void changeCellAttribute(int[] rows, int[] columns, Object
* command) { cellAtt.changeAttribute(rows, columns, command); }
*/
}
/**
* @version 1.0 11/22/98
*/
class DefaultCellAttribute
// implements CellAttribute ,CellSpan {
implements CellAttribute, CellSpan, ColoredCell, CellFont {
//
// !!!! CAUTION !!!!!
// these values must be synchronized to Table data
//
protected int rowSize;
protected int columnSize;
protected int[][][] span; // CellSpan
protected Color[][] foreground; // ColoredCell
protected Color[][] background; //
protected Font[][] font; // CellFont
public DefaultCellAttribute() {
this(1, 1);
}
public DefaultCellAttribute(int numRows, int numColumns) {
setSize(new Dimension(numColumns, numRows));
}
protected void initValue() {
for (int i = 0; i < span.length; i++) {
for (int j = 0; j < span[i].length; j++) {
span[i][j][CellSpan.COLUMN] = 1;
span[i][j][CellSpan.ROW] = 1;
}
}
}
//
// CellSpan
//
public int[] getSpan(int row, int column) {
if (isOutOfBounds(row, column)) {
int[] ret_code = { 1, 1 };
return ret_code;
}
return span[row][column];
}
public void setSpan(int[] span, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.span[row][column] = span;
}
public boolean isVisible(int row, int column) {
if (isOutOfBounds(row, column))
return false;
if ((span[row][column][CellSpan.COLUMN] < 1)
|| (span[row][column][CellSpan.ROW] < 1))
return false;
return true;
}
public void combine(int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
int rowSpan = rows.length;
int columnSpan = columns.length;
int startRow = rows[0];
int startColumn = columns[0];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
|| (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
//System.out.println("can"t combine");
return;
}
}
}
for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
//System.out.println("r " +ii +" c " +jj);
}
}
span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
span[startRow][startColumn][CellSpan.ROW] = rowSpan;
}
public void split(int row, int column) {
if (isOutOfBounds(row, column))
return;
int columnSpan = span[row][column][CellSpan.COLUMN];
int rowSpan = span[row][column][CellSpan.ROW];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
span[row + i][column + j][CellSpan.COLUMN] = 1;
span[row + i][column + j][CellSpan.ROW] = 1;
}
}
}
//
// ColoredCell
//
public Color getForeground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return foreground[row][column];
}
public void setForeground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
foreground[row][column] = color;
}
public void setForeground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(foreground, color, rows, columns);
}
public Color getBackground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return background[row][column];
}
public void setBackground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
background[row][column] = color;
}
public void setBackground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(background, color, rows, columns);
}
//
//
// CellFont
//
public Font getFont(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return font[row][column];
}
public void setFont(Font font, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.font[row][column] = font;
}
public void setFont(Font font, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(this.font, font, rows, columns);
}
//
//
// CellAttribute
//
public void addColumn() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows][numColumns + 1][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numRows; i++) {
span[i][numColumns][CellSpan.COLUMN] = 1;
span[i][numColumns][CellSpan.ROW] = 1;
}
}
public void addRow() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numColumns; i++) {
span[numRows][i][CellSpan.COLUMN] = 1;
span[numRows][i][CellSpan.ROW] = 1;
}
}
public void insertRow(int row) {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
if (0 < row) {
System.arraycopy(oldSpan, 0, span, 0, row - 1);
}
System.arraycopy(oldSpan, 0, span, row, numRows - row);
for (int i = 0; i < numColumns; i++) {
span[row][i][CellSpan.COLUMN] = 1;
span[row][i][CellSpan.ROW] = 1;
}
}
public Dimension getSize() {
return new Dimension(rowSize, columnSize);
}
public void setSize(Dimension size) {
columnSize = size.width;
rowSize = size.height;
span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
foreground = new Color[rowSize][columnSize];
background = new Color[rowSize][columnSize];
font = new Font[rowSize][columnSize];
initValue();
}
/*
* public void changeAttribute(int row, int column, Object command) { }
*
* public void changeAttribute(int[] rows, int[] columns, Object command) { }
*/
protected boolean isOutOfBounds(int row, int column) {
if ((row < 0) || (rowSize <= row) || (column < 0)
|| (columnSize <= column)) {
return true;
}
return false;
}
protected boolean isOutOfBounds(int[] rows, int[] columns) {
for (int i = 0; i < rows.length; i++) {
if ((rows[i] < 0) || (rowSize <= rows[i]))
return true;
}
for (int i = 0; i < columns.length; i++) {
if ((columns[i] < 0) || (columnSize <= columns[i]))
return true;
}
return false;
}
protected void setValues(Object[][] target, Object value, int[] rows,
int[] columns) {
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
for (int j = 0; j < columns.length; j++) {
int column = columns[j];
target[row][column] = value;
}
}
}
}
/**
* @version 1.0 11/22/98
*/
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/22/98
*/
interface CellAttribute {
public void addColumn();
public void addRow();
public void insertRow(int row);
public Dimension getSize();
public void setSize(Dimension size);
}
interface ColoredCell {
public Color getForeground(int row, int column);
public void setForeground(Color color, int row, int column);
public void setForeground(Color color, int[] rows, int[] columns);
public Color getBackground(int row, int column);
public void setBackground(Color color, int row, int column);
public void setBackground(Color color, int[] rows, int[] columns);
}
/**
* @version 1.0 11/22/98
*/
class AttributiveCellRenderer extends JLabel implements TableCellRenderer {
protected static Border noFocusBorder;
public AttributiveCellRenderer() {
noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setOpaque(true);
setBorder(noFocusBorder);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Color foreground = null;
Color background = null;
Font font = null;
TableModel model = table.getModel();
if (model instanceof AttributiveCellTableModel) {
CellAttribute cellAtt = ((AttributiveCellTableModel) model)
.getCellAttribute();
if (cellAtt instanceof ColoredCell) {
foreground = ((ColoredCell) cellAtt).getForeground(row, column);
background = ((ColoredCell) cellAtt).getBackground(row, column);
}
if (cellAtt instanceof CellFont) {
font = ((CellFont) cellAtt).getFont(row, column);
}
}
if (isSelected) {
setForeground((foreground != null) ? foreground : table
.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground((foreground != null) ? foreground : table
.getForeground());
setBackground((background != null) ? background : table
.getBackground());
}
setFont((font != null) ? font : table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
setForeground((foreground != null) ? foreground : UIManager
.getColor("Table.focusCellForeground"));
setBackground(UIManager.getColor("Table.focusCellBackground"));
}
} else {
setBorder(noFocusBorder);
}
setValue(value);
return this;
}
protected void setValue(Object value) {
setText((value == null) ? "" : value.toString());
}
}
/**
* @version 1.0 11/22/98
*/
class TextPreviewLabel extends JLabel {
private String sampleText = " Sample Text Sample Text ";
boolean isForgroundSelection;
public TextPreviewLabel() {
this(Color.black, Color.white, true);
}
public TextPreviewLabel(Color fore, Color back, boolean isForgroundSelection) {
setOpaque(true);
setForeground(fore);
setBackground(back);
this.isForgroundSelection = isForgroundSelection;
setText(sampleText);
}
public void setForeground(Color col) {
if (isForgroundSelection) {
super.setForeground(col);
} else {
super.setBackground(col);
}
}
}
class ColorChooserDialog extends JDialog {
private Color initialColor;
private Color retColor;
private JColorChooser chooserPane;
public ColorChooserDialog(Component c, String title,
final JColorChooser chooserPane) {
super(JOptionPane.getFrameForComponent(c), title, true);
setResizable(false);
this.chooserPane = chooserPane;
String okString = UIManager.getString("ColorChooser.okText");
String cancelString = UIManager.getString("ColorChooser.cancelText");
String resetString = UIManager.getString("ColorChooser.resetText");
Container contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(chooserPane, BorderLayout.CENTER);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.CENTER));
JButton okButton = new JButton(okString);
getRootPane().setDefaultButton(okButton);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
retColor = chooserPane.getColor();
setVisible(false);
}
});
buttonPane.add(okButton);
JButton cancelButton = new JButton(cancelString);
cancelButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
retColor = null;
setVisible(false);
}
});
buttonPane.add(cancelButton);
JButton resetButton = new JButton(resetString);
resetButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
chooserPane.setColor(initialColor);
}
});
buttonPane.add(resetButton);
contentPane.add(buttonPane, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(c);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
}
});
}
public Color getColor() {
return retColor;
}
}
class TextColorChooser extends JColorChooser {
public TextColorChooser(Color target, Color reference,
boolean isForgroundSelection) {
super(target);
if (isForgroundSelection) {
setPreviewPanel(new TextPreviewLabel(target, reference,
isForgroundSelection));
} else {
setPreviewPanel(new TextPreviewLabel(reference, target,
isForgroundSelection));
}
updateUI();
}
public Color showDialog(Component component, String title) {
ColorChooserDialog dialog = new ColorChooserDialog(component, title,
this);
dialog.show();
Color col = dialog.getColor();
dialog.dispose();
return col;
}
}
interface CellFont {
public Font getFont(int row, int column);
public void setFont(Font font, int row, int column);
public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
public final int ROW = 0;
public final int COLUMN = 1;
public int[] getSpan(int row, int column);
public void setSpan(int[] span, int row, int column);
public boolean isVisible(int row, int column);
public void combine(int[] rows, int[] columns);
public void split(int row, int column);
}
multiple Row Header Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) (swing#1356,#1454) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.ListSelectionModel;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
/* ----------------------------------------------
* | SNo. |
* ----------------------------------------------
* | | 1 |
* | Name |-----------------------------------
* | | 2 |
* ----------------------------------------------
* | | 1 |
* | |-----------------------------------
* | Language | 2 |
* | |-----------------------------------
* | | 3 |
* ----------------------------------------------
*/
/**
* @version 1.0 03/06/99
*/
public class MultipleRowHeaderExample extends JFrame {
Object[][] data;
Object[] column;
JTable table;
MultiSpanCellTable fixedTable;
public MultipleRowHeaderExample() {
super("Multiple Row Header Example");
setSize(400, 150);
data = new Object[][] { { "SNo.", "" }, { "Name", "1" }, { "", "2" },
{ "Language", "1" }, { "", "2" }, { "", "3" } };
column = new Object[] { "", "" };
AttributiveCellTableModel fixedModel = new AttributiveCellTableModel(
data, column) {
public boolean CellEditable(int row, int col) {
return false;
}
};
CellSpan cellAtt = (CellSpan) fixedModel.getCellAttribute();
cellAtt.rubine(new int[] { 0 }, new int[] { 0, 1 });
cellAtt.rubine(new int[] { 1, 2 }, new int[] { 0 });
cellAtt.rubine(new int[] { 3, 4, 5 }, new int[] { 0 });
DefaultTableModel model = new DefaultTableModel(data.length, 3);
fixedTable = new MultiSpanCellTable(fixedModel);
table = new JTable(model);
fixedTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
fixedTable.setDefaultRenderer(Object.class, new RowHeaderRenderer(
fixedTable));
fixedTable.setGridColor(table.getTableHeader().getBackground());
JScrollPane scroll = new JScrollPane(table);
JViewport viewport = new JViewport();
viewport.setView(fixedTable);
viewport.setPreferredSize(fixedTable.getPreferredSize());
scroll.setRowHeaderView(viewport);
getContentPane().add(scroll, BorderLayout.CENTER);
}
public static void main(String[] args) {
MultipleRowHeaderExample frame = new MultipleRowHeaderExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
class RowHeaderRenderer extends JLabel implements TableCellRenderer {
RowHeaderRenderer(JTable table) {
JTableHeader header = table.getTableHeader();
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(CENTER);
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
setText((value == null) ? "" : value.toString());
return this;
}
}
}
class AttributiveCellTableModel extends DefaultTableModel {
protected CellAttribute cellAtt;
public AttributiveCellTableModel() {
this((Vector) null, 0);
}
public AttributiveCellTableModel(int numRows, int numColumns) {
Vector names = new Vector(numColumns);
names.setSize(numColumns);
setColumnIdentifiers(names);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, numColumns);
}
public AttributiveCellTableModel(Vector columnNames, int numRows) {
setColumnIdentifiers(columnNames);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows, columnNames.size());
}
public AttributiveCellTableModel(Object[] columnNames, int numRows) {
this(convertToVector(columnNames), numRows);
}
public AttributiveCellTableModel(Vector data, Vector columnNames) {
setDataVector(data, columnNames);
}
public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
public void setDataVector(Vector newData, Vector columnNames) {
if (newData == null)
throw new IllegalArgumentException(
"setDataVector() - Null parameter");
dataVector = new Vector(0);
setColumnIdentifiers(columnNames);
dataVector = newData;
//
cellAtt = new DefaultCellAttribute(dataVector.size(), columnIdentifiers
.size());
newRowsAdded(new TableModelEvent(this, 0, getRowCount() - 1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public void addColumn(Object columnName, Vector columnData) {
if (columnName == null)
throw new IllegalArgumentException("addColumn() - null parameter");
columnIdentifiers.addElement(columnName);
int index = 0;
Enumeration enumeration = dataVector.elements();
while (enumeration.hasMoreElements()) {
Object value;
if ((columnData != null) && (index < columnData.size()))
value = columnData.elementAt(index);
else
value = null;
((Vector) enumeration.nextElement()).addElement(value);
index++;
}
//
cellAtt.addColumn();
fireTableStructureChanged();
}
public void addRow(Vector rowData) {
Vector newData = null;
if (rowData == null) {
newData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.addElement(newData);
//
cellAtt.addRow();
newRowsAdded(new TableModelEvent(this, getRowCount() - 1,
getRowCount() - 1, TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT));
}
public void insertRow(int row, Vector rowData) {
if (rowData == null) {
rowData = new Vector(getColumnCount());
} else {
rowData.setSize(getColumnCount());
}
dataVector.insertElementAt(rowData, row);
//
cellAtt.insertRow(row);
newRowsAdded(new TableModelEvent(this, row, row,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public CellAttribute getCellAttribute() {
return cellAtt;
}
public void setCellAttribute(CellAttribute newCellAtt) {
int numColumns = getColumnCount();
int numRows = getRowCount();
if ((newCellAtt.getSize().width != numColumns)
|| (newCellAtt.getSize().height != numRows)) {
newCellAtt.setSize(new Dimension(numRows, numColumns));
}
cellAtt = newCellAtt;
fireTableDataChanged();
}
/*
* public void changeCellAttribute(int row, int column, Object command) {
* cellAtt.changeAttribute(row, column, command); }
*
* public void changeCellAttribute(int[] rows, int[] columns, Object
* command) { cellAtt.changeAttribute(rows, columns, command); }
*/
}
class DefaultCellAttribute
//implements CellAttribute ,CellSpan {
implements CellAttribute, CellSpan, ColoredCell, CellFont {
//
// !!!! CAUTION !!!!!
// these values must be synchronized to Table data
//
protected int rowSize;
protected int columnSize;
protected int[][][] span; // CellSpan
protected Color[][] foreground; // ColoredCell
protected Color[][] background; //
protected Font[][] font; // CellFont
public DefaultCellAttribute() {
this(1, 1);
}
public DefaultCellAttribute(int numRows, int numColumns) {
setSize(new Dimension(numColumns, numRows));
}
protected void initValue() {
for (int i = 0; i < span.length; i++) {
for (int j = 0; j < span[i].length; j++) {
span[i][j][CellSpan.COLUMN] = 1;
span[i][j][CellSpan.ROW] = 1;
}
}
}
//
// CellSpan
//
public int[] getSpan(int row, int column) {
if (isOutOfBounds(row, column)) {
int[] ret_code = { 1, 1 };
return ret_code;
}
return span[row][column];
}
public void setSpan(int[] span, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.span[row][column] = span;
}
public boolean isVisible(int row, int column) {
if (isOutOfBounds(row, column))
return false;
if ((span[row][column][CellSpan.COLUMN] < 1)
|| (span[row][column][CellSpan.ROW] < 1))
return false;
return true;
}
public void combine(int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
int rowSpan = rows.length;
int columnSpan = columns.length;
int startRow = rows[0];
int startColumn = columns[0];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
if ((span[startRow + i][startColumn + j][CellSpan.COLUMN] != 1)
|| (span[startRow + i][startColumn + j][CellSpan.ROW] != 1)) {
//System.out.println("can"t combine");
return;
}
}
}
for (int i = 0, ii = 0; i < rowSpan; i++, ii--) {
for (int j = 0, jj = 0; j < columnSpan; j++, jj--) {
span[startRow + i][startColumn + j][CellSpan.COLUMN] = jj;
span[startRow + i][startColumn + j][CellSpan.ROW] = ii;
//System.out.println("r " +ii +" c " +jj);
}
}
span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
span[startRow][startColumn][CellSpan.ROW] = rowSpan;
}
public void split(int row, int column) {
if (isOutOfBounds(row, column))
return;
int columnSpan = span[row][column][CellSpan.COLUMN];
int rowSpan = span[row][column][CellSpan.ROW];
for (int i = 0; i < rowSpan; i++) {
for (int j = 0; j < columnSpan; j++) {
span[row + i][column + j][CellSpan.COLUMN] = 1;
span[row + i][column + j][CellSpan.ROW] = 1;
}
}
}
//
// ColoredCell
//
public Color getForeground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return foreground[row][column];
}
public void setForeground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
foreground[row][column] = color;
}
public void setForeground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(foreground, color, rows, columns);
}
public Color getBackground(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return background[row][column];
}
public void setBackground(Color color, int row, int column) {
if (isOutOfBounds(row, column))
return;
background[row][column] = color;
}
public void setBackground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(background, color, rows, columns);
}
//
//
// CellFont
//
public Font getFont(int row, int column) {
if (isOutOfBounds(row, column))
return null;
return font[row][column];
}
public void setFont(Font font, int row, int column) {
if (isOutOfBounds(row, column))
return;
this.font[row][column] = font;
}
public void setFont(Font font, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns))
return;
setValues(this.font, font, rows, columns);
}
//
//
// CellAttribute
//
public void addColumn() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows][numColumns + 1][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numRows; i++) {
span[i][numColumns][CellSpan.COLUMN] = 1;
span[i][numColumns][CellSpan.ROW] = 1;
}
}
public void addRow() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
System.arraycopy(oldSpan, 0, span, 0, numRows);
for (int i = 0; i < numColumns; i++) {
span[numRows][i][CellSpan.COLUMN] = 1;
span[numRows][i][CellSpan.ROW] = 1;
}
}
public void insertRow(int row) {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
if (0 < row) {
System.arraycopy(oldSpan, 0, span, 0, row - 1);
}
System.arraycopy(oldSpan, 0, span, row, numRows - row);
for (int i = 0; i < numColumns; i++) {
span[row][i][CellSpan.COLUMN] = 1;
span[row][i][CellSpan.ROW] = 1;
}
}
public Dimension getSize() {
return new Dimension(rowSize, columnSize);
}
public void setSize(Dimension size) {
columnSize = size.width;
rowSize = size.height;
span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
foreground = new Color[rowSize][columnSize];
background = new Color[rowSize][columnSize];
font = new Font[rowSize][columnSize];
initValue();
}
/*
* public void changeAttribute(int row, int column, Object command) { }
*
* public void changeAttribute(int[] rows, int[] columns, Object command) { }
*/
protected boolean isOutOfBounds(int row, int column) {
if ((row < 0) || (rowSize <= row) || (column < 0)
|| (columnSize <= column)) {
return true;
}
return false;
}
protected boolean isOutOfBounds(int[] rows, int[] columns) {
for (int i = 0; i < rows.length; i++) {
if ((rows[i] < 0) || (rowSize <= rows[i]))
return true;
}
for (int i = 0; i < columns.length; i++) {
if ((columns[i] < 0) || (columnSize <= columns[i]))
return true;
}
return false;
}
protected void setValues(Object[][] target, Object value, int[] rows,
int[] columns) {
for (int i = 0; i < rows.length; i++) {
int row = rows[i];
for (int j = 0; j < columns.length; j++) {
int column = columns[j];
target[row][column] = value;
}
}
}
}
interface CellAttribute {
public void addColumn();
public void addRow();
public void insertRow(int row);
public Dimension getSize();
public void setSize(Dimension size);
}
interface ColoredCell {
public Color getForeground(int row, int column);
public void setForeground(Color color, int row, int column);
public void setForeground(Color color, int[] rows, int[] columns);
public Color getBackground(int row, int column);
public void setBackground(Color color, int row, int column);
public void setBackground(Color color, int[] rows, int[] columns);
}
interface CellFont {
public Font getFont(int row, int column);
public void setFont(Font font, int row, int column);
public void setFont(Font font, int[] rows, int[] columns);
}
interface CellSpan {
public final int ROW = 0;
public final int COLUMN = 1;
public int[] getSpan(int row, int column);
public void setSpan(int[] span, int row, int column);
public boolean isVisible(int row, int column);
public void combine(int[] rows, int[] columns);
public void split(int row, int column);
}
class MultiSpanCellTable extends JTable {
public MultiSpanCellTable(TableModel model) {
super(model);
setUI(new MultiSpanCellTableUI());
getTableHeader().setReorderingAllowed(false);
setCellSelectionEnabled(true);
setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle sRect = super.getCellRect(row, column, includeSpacing);
if ((row < 0) || (column < 0) || (getRowCount() <= row)
|| (getColumnCount() <= column)) {
return sRect;
}
CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
.getCellAttribute();
if (!cellAtt.isVisible(row, column)) {
int temp_row = row;
int temp_column = column;
row += cellAtt.getSpan(temp_row, temp_column)[CellSpan.ROW];
column += cellAtt.getSpan(temp_row, temp_column)[CellSpan.COLUMN];
}
int[] n = cellAtt.getSpan(row, column);
int index = 0;
int columnMargin = getColumnModel().getColumnMargin();
Rectangle cellFrame = new Rectangle();
int aCellHeight = rowHeight + rowMargin;
cellFrame.y = row * aCellHeight;
cellFrame.height = n[CellSpan.ROW] * aCellHeight;
Enumeration enumeration = getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn) enumeration.nextElement();
cellFrame.width = aColumn.getWidth() + columnMargin;
if (index == column)
break;
cellFrame.x += cellFrame.width;
index++;
}
for (int i = 0; i < n[CellSpan.COLUMN] - 1; i++) {
TableColumn aColumn = (TableColumn) enumeration.nextElement();
cellFrame.width += aColumn.getWidth() + columnMargin;
}
if (!includeSpacing) {
Dimension spacing = getIntercellSpacing();
cellFrame.setBounds(cellFrame.x + spacing.width / 2, cellFrame.y
+ spacing.height / 2, cellFrame.width - spacing.width,
cellFrame.height - spacing.height);
}
return cellFrame;
}
private int[] rowColumnAtPoint(Point point) {
int[] retValue = { -1, -1 };
int row = point.y / (rowHeight + rowMargin);
if ((row < 0) || (getRowCount() <= row))
return retValue;
int column = getColumnModel().getColumnIndexAtX(point.x);
CellSpan cellAtt = (CellSpan) ((AttributiveCellTableModel) getModel())
.getCellAttribute();
if (cellAtt.isVisible(row, column)) {
retValue[CellSpan.COLUMN] = column;
retValue[CellSpan.ROW] = row;
return retValue;
}
retValue[CellSpan.COLUMN] = column
+ cellAtt.getSpan(row, column)[CellSpan.COLUMN];
retValue[CellSpan.ROW] = row
+ cellAtt.getSpan(row, column)[CellSpan.ROW];
return retValue;
}
public int rowAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.ROW];
}
public int columnAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.COLUMN];
}
public void columnSelectionChanged(ListSelectionEvent e) {
repaint();
}
public void valueChanged(ListSelectionEvent e) {
int firstIndex = e.getFirstIndex();
int lastIndex = e.getLastIndex();
if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
repaint();
}
Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
int numCoumns = getColumnCount();
int index = firstIndex;
for (int i = 0; i < numCoumns; i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
index = lastIndex;
for (int i = 0; i < numCoumns; i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width,
dirtyRegion.height);
}
}
class MultiSpanCellTableUI extends BasicTableUI {
public void paint(Graphics g, JComponent c) {
Rectangle oldClipBounds = g.getClipBounds();
Rectangle clipBounds = new Rectangle(oldClipBounds);
int tableWidth = table.getColumnModel().getTotalColumnWidth();
clipBounds.width = Math.min(clipBounds.width, tableWidth);
g.setClip(clipBounds);
int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
int lastIndex = table.getRowCount() - 1;
Rectangle rowRect = new Rectangle(0, 0, tableWidth, table
.getRowHeight()
+ table.getRowMargin());
rowRect.y = firstIndex * rowRect.height;
for (int index = firstIndex; index <= lastIndex; index++) {
if (rowRect.intersects(clipBounds)) {
//System.out.println(); // debug
//System.out.print("" + index +": "); // row
paintRow(g, index);
}
rowRect.y += rowRect.height;
}
g.setClip(oldClipBounds);
}
private void paintRow(Graphics g, int row) {
Rectangle rect = g.getClipBounds();
boolean drawn = false;
AttributiveCellTableModel tableModel = (AttributiveCellTableModel) table
.getModel();
CellSpan cellAtt = (CellSpan) tableModel.getCellAttribute();
int numColumns = table.getColumnCount();
for (int column = 0; column < numColumns; column++) {
Rectangle cellRect = table.getCellRect(row, column, true);
int cellRow, cellColumn;
if (cellAtt.isVisible(row, column)) {
cellRow = row;
cellColumn = column;
// System.out.print(" "+column+" "); // debug
} else {
cellRow = row + cellAtt.getSpan(row, column)[CellSpan.ROW];
cellColumn = column
+ cellAtt.getSpan(row, column)[CellSpan.COLUMN];
// System.out.print(" ("+column+")"); // debug
}
if (cellRect.intersects(rect)) {
drawn = true;
paintCell(g, cellRect, cellRow, cellColumn);
} else {
if (drawn)
break;
}
}
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
int spacingHeight = table.getRowMargin();
int spacingWidth = table.getColumnModel().getColumnMargin();
Color c = g.getColor();
g.setColor(table.getGridColor());
g.drawRect(cellRect.x, cellRect.y, cellRect.width - 1,
cellRect.height - 1);
g.setColor(c);
cellRect.setBounds(cellRect.x + spacingWidth / 2, cellRect.y
+ spacingHeight / 2, cellRect.width - spacingWidth,
cellRect.height - spacingHeight);
if (table.isEditing() && table.getEditingRow() == row
&& table.getEditingColumn() == column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
} else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if (component.getParent() == null) {
rendererPane.add(component);
}
rendererPane.paintComponent(g, component, table, cellRect.x,
cellRect.y, cellRect.width, cellRect.height, true);
}
}
}
Multi Span Cell Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableModelEvent;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
/**
* @version 1.0 11/26/98
*/
public class MultiSpanCellTableExample extends JFrame {
MultiSpanCellTableExample() {
super( "Multi-Span Cell Example" );
AttributiveCellTableModel ml = new AttributiveCellTableModel(10,6);
/*
AttributiveCellTableModel ml = new AttributiveCellTableModel(10,6) {
public Object getValueAt(int row, int col) {
return "" + row + ","+ col;
}
};
*/
final CellSpan cellAtt =(CellSpan)ml.getCellAttribute();
final MultiSpanCellTable table = new MultiSpanCellTable( ml );
JScrollPane scroll = new JScrollPane( table );
JButton b_one = new JButton("Combine");
b_one.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int[] columns = table.getSelectedColumns();
int[] rows = table.getSelectedRows();
cellAtt.rubine(rows,columns);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
JButton b_split = new JButton("Split");
b_split.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int column = table.getSelectedColumn();
int row = table.getSelectedRow();
cellAtt.split(row,column);
table.clearSelection();
table.revalidate();
table.repaint();
}
});
JPanel p_buttons = new JPanel();
p_buttons.setLayout(new GridLayout(2,1));
p_buttons.add(b_one);
p_buttons.add(b_split);
Box box = new Box(BoxLayout.X_AXIS);
box.add(scroll);
box.add(new JSeparator(SwingConstants.HORIZONTAL));
box.add(p_buttons);
getContentPane().add( box );
setSize( 400, 200 );
setVisible(true);
}
public static void main(String[] args) {
MultiSpanCellTableExample frame = new MultiSpanCellTableExample();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
}
});
}
}
/**
* @version 1.0 11/22/98
*/
class AttributiveCellTableModel extends DefaultTableModel {
protected CellAttribute cellAtt;
public AttributiveCellTableModel() {
this((Vector)null, 0);
}
public AttributiveCellTableModel(int numRows, int numColumns) {
Vector names = new Vector(numColumns);
names.setSize(numColumns);
setColumnIdentifiers(names);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows,numColumns);
}
public AttributiveCellTableModel(Vector columnNames, int numRows) {
setColumnIdentifiers(columnNames);
dataVector = new Vector();
setNumRows(numRows);
cellAtt = new DefaultCellAttribute(numRows,columnNames.size());
}
public AttributiveCellTableModel(Object[] columnNames, int numRows) {
this(convertToVector(columnNames), numRows);
}
public AttributiveCellTableModel(Vector data, Vector columnNames) {
setDataVector(data, columnNames);
}
public AttributiveCellTableModel(Object[][] data, Object[] columnNames) {
setDataVector(data, columnNames);
}
public void setDataVector(Vector newData, Vector columnNames) {
if (newData == null)
throw new IllegalArgumentException("setDataVector() - Null parameter");
dataVector = new Vector(0);
setColumnIdentifiers(columnNames);
dataVector = newData;
//
cellAtt = new DefaultCellAttribute(dataVector.size(),
columnIdentifiers.size());
newRowsAdded(new TableModelEvent(this, 0, getRowCount()-1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public void addColumn(Object columnName, Vector columnData) {
if (columnName == null)
throw new IllegalArgumentException("addColumn() - null parameter");
columnIdentifiers.addElement(columnName);
int index = 0;
Enumeration eeration = dataVector.elements();
while (eeration.hasMoreElements()) {
Object value;
if ((columnData != null) && (index < columnData.size()))
value = columnData.elementAt(index);
else
value = null;
((Vector)eeration.nextElement()).addElement(value);
index++;
}
//
cellAtt.addColumn();
fireTableStructureChanged();
}
public void addRow(Vector rowData) {
Vector newData = null;
if (rowData == null) {
newData = new Vector(getColumnCount());
}
else {
rowData.setSize(getColumnCount());
}
dataVector.addElement(newData);
//
cellAtt.addRow();
newRowsAdded(new TableModelEvent(this, getRowCount()-1, getRowCount()-1,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public void insertRow(int row, Vector rowData) {
if (rowData == null) {
rowData = new Vector(getColumnCount());
}
else {
rowData.setSize(getColumnCount());
}
dataVector.insertElementAt(rowData, row);
//
cellAtt.insertRow(row);
newRowsAdded(new TableModelEvent(this, row, row,
TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
}
public CellAttribute getCellAttribute() {
return cellAtt;
}
public void setCellAttribute(CellAttribute newCellAtt) {
int numColumns = getColumnCount();
int numRows = getRowCount();
if ((newCellAtt.getSize().width != numColumns) ||
(newCellAtt.getSize().height != numRows)) {
newCellAtt.setSize(new Dimension(numRows, numColumns));
}
cellAtt = newCellAtt;
fireTableDataChanged();
}
/*
public void changeCellAttribute(int row, int column, Object command) {
cellAtt.changeAttribute(row, column, command);
}
public void changeCellAttribute(int[] rows, int[] columns, Object command) {
cellAtt.changeAttribute(rows, columns, command);
}
*/
}
/**
* @version 1.0 11/22/98
*/
class DefaultCellAttribute
// implements CellAttribute ,CellSpan {
implements CellAttribute ,CellSpan ,ColoredCell ,CellFont {
//
// !!!! CAUTION !!!!!
// these values must be synchronized to Table data
//
protected int rowSize;
protected int columnSize;
protected int[][][] span; // CellSpan
protected Color[][] foreground; // ColoredCell
protected Color[][] background; //
protected Font[][] font; // CellFont
public DefaultCellAttribute() {
this(1,1);
}
public DefaultCellAttribute(int numRows, int numColumns) {
setSize(new Dimension(numColumns, numRows));
}
protected void initValue() {
for(int i=0; i<span.length;i++) {
for(int j=0; j<span[i].length; j++) {
span[i][j][CellSpan.COLUMN] = 1;
span[i][j][CellSpan.ROW] = 1;
}
}
}
//
// CellSpan
//
public int[] getSpan(int row, int column) {
if (isOutOfBounds(row, column)) {
int[] ret_code = {1,1};
return ret_code;
}
return span[row][column];
}
public void setSpan(int[] span, int row, int column) {
if (isOutOfBounds(row, column)) return;
this.span[row][column] = span;
}
public boolean isVisible(int row, int column) {
if (isOutOfBounds(row, column)) return false;
if ((span[row][column][CellSpan.COLUMN] < 1)
||(span[row][column][CellSpan.ROW] < 1)) return false;
return true;
}
public void combine(int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) return;
int rowSpan = rows.length;
int columnSpan = columns.length;
int startRow = rows[0];
int startColumn = columns[0];
for (int i=0;i<rowSpan;i++) {
for (int j=0;j<columnSpan;j++) {
if ((span[startRow +i][startColumn +j][CellSpan.COLUMN] != 1)
||(span[startRow +i][startColumn +j][CellSpan.ROW] != 1)) {
//System.out.println("can"t combine");
return ;
}
}
}
for (int i=0,ii=0;i<rowSpan;i++,ii--) {
for (int j=0,jj=0;j<columnSpan;j++,jj--) {
span[startRow +i][startColumn +j][CellSpan.COLUMN] = jj;
span[startRow +i][startColumn +j][CellSpan.ROW] = ii;
//System.out.println("r " +ii +" c " +jj);
}
}
span[startRow][startColumn][CellSpan.COLUMN] = columnSpan;
span[startRow][startColumn][CellSpan.ROW] = rowSpan;
}
public void split(int row, int column) {
if (isOutOfBounds(row, column)) return;
int columnSpan = span[row][column][CellSpan.COLUMN];
int rowSpan = span[row][column][CellSpan.ROW];
for (int i=0;i<rowSpan;i++) {
for (int j=0;j<columnSpan;j++) {
span[row +i][column +j][CellSpan.COLUMN] = 1;
span[row +i][column +j][CellSpan.ROW] = 1;
}
}
}
//
// ColoredCell
//
public Color getForeground(int row, int column) {
if (isOutOfBounds(row, column)) return null;
return foreground[row][column];
}
public void setForeground(Color color, int row, int column) {
if (isOutOfBounds(row, column)) return;
foreground[row][column] = color;
}
public void setForeground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) return;
setValues(foreground, color, rows, columns);
}
public Color getBackground(int row, int column) {
if (isOutOfBounds(row, column)) return null;
return background[row][column];
}
public void setBackground(Color color, int row, int column) {
if (isOutOfBounds(row, column)) return;
background[row][column] = color;
}
public void setBackground(Color color, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) return;
setValues(background, color, rows, columns);
}
//
//
// CellFont
//
public Font getFont(int row, int column) {
if (isOutOfBounds(row, column)) return null;
return font[row][column];
}
public void setFont(Font font, int row, int column) {
if (isOutOfBounds(row, column)) return;
this.font[row][column] = font;
}
public void setFont(Font font, int[] rows, int[] columns) {
if (isOutOfBounds(rows, columns)) return;
setValues(this.font, font, rows, columns);
}
//
//
// CellAttribute
//
public void addColumn() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows][numColumns + 1][2];
System.arraycopy(oldSpan,0,span,0,numRows);
for (int i=0;i<numRows;i++) {
span[i][numColumns][CellSpan.COLUMN] = 1;
span[i][numColumns][CellSpan.ROW] = 1;
}
}
public void addRow() {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
System.arraycopy(oldSpan,0,span,0,numRows);
for (int i=0;i<numColumns;i++) {
span[numRows][i][CellSpan.COLUMN] = 1;
span[numRows][i][CellSpan.ROW] = 1;
}
}
public void insertRow(int row) {
int[][][] oldSpan = span;
int numRows = oldSpan.length;
int numColumns = oldSpan[0].length;
span = new int[numRows + 1][numColumns][2];
if (0 < row) {
System.arraycopy(oldSpan,0,span,0,row-1);
}
System.arraycopy(oldSpan,0,span,row,numRows - row);
for (int i=0;i<numColumns;i++) {
span[row][i][CellSpan.COLUMN] = 1;
span[row][i][CellSpan.ROW] = 1;
}
}
public Dimension getSize() {
return new Dimension(rowSize, columnSize);
}
public void setSize(Dimension size) {
columnSize = size.width;
rowSize = size.height;
span = new int[rowSize][columnSize][2]; // 2: COLUMN,ROW
foreground = new Color[rowSize][columnSize];
background = new Color[rowSize][columnSize];
font = new Font[rowSize][columnSize];
initValue();
}
/*
public void changeAttribute(int row, int column, Object command) {
}
public void changeAttribute(int[] rows, int[] columns, Object command) {
}
*/
protected boolean isOutOfBounds(int row, int column) {
if ((row < 0)||(rowSize <= row)
||(column < 0)||(columnSize <= column)) {
return true;
}
return false;
}
protected boolean isOutOfBounds(int[] rows, int[] columns) {
for (int i=0;i<rows.length;i++) {
if ((rows[i] < 0)||(rowSize <= rows[i])) return true;
}
for (int i=0;i<columns.length;i++) {
if ((columns[i] < 0)||(columnSize <= columns[i])) return true;
}
return false;
}
protected void setValues(Object[][] target, Object value,
int[] rows, int[] columns) {
for (int i=0;i<rows.length;i++) {
int row = rows[i];
for (int j=0;j<columns.length;j++) {
int column = columns[j];
target[row][column] = value;
}
}
}
}
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/22/98
*/
interface CellAttribute {
public void addColumn();
public void addRow();
public void insertRow(int row);
public Dimension getSize();
public void setSize(Dimension size);
}
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/22/98
*/
interface CellSpan {
public final int ROW = 0;
public final int COLUMN = 1;
public int[] getSpan(int row, int column);
public void setSpan(int[] span, int row, int column);
public boolean isVisible(int row, int column);
public void combine(int[] rows, int[] columns);
public void split(int row, int column);
}
/*
* (swing1.1beta3)
*
*/
/**
* @version 1.0 11/26/98
*/
class MultiSpanCellTable extends JTable {
public MultiSpanCellTable(TableModel model) {
super(model);
setUI(new MultiSpanCellTableUI());
getTableHeader().setReorderingAllowed(false);
setCellSelectionEnabled(true);
setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle sRect = super.getCellRect(row,column,includeSpacing);
if ((row <0) || (column<0) ||
(getRowCount() <= row) || (getColumnCount() <= column)) {
return sRect;
}
CellSpan cellAtt = (CellSpan)((AttributiveCellTableModel)getModel()).getCellAttribute();
if (! cellAtt.isVisible(row,column)) {
int temp_row = row;
int temp_column = column;
row += cellAtt.getSpan(temp_row,temp_column)[CellSpan.ROW];
column += cellAtt.getSpan(temp_row,temp_column)[CellSpan.COLUMN];
}
int[] n = cellAtt.getSpan(row,column);
int index = 0;
int columnMargin = getColumnModel().getColumnMargin();
Rectangle cellFrame = new Rectangle();
int aCellHeight = rowHeight + rowMargin;
cellFrame.y = row * aCellHeight;
cellFrame.height = n[CellSpan.ROW] * aCellHeight;
Enumeration eeration = getColumnModel().getColumns();
while (eeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)eeration.nextElement();
cellFrame.width = aColumn.getWidth() + columnMargin;
if (index == column) break;
cellFrame.x += cellFrame.width;
index++;
}
for (int i=0;i< n[CellSpan.COLUMN]-1;i++) {
TableColumn aColumn = (TableColumn)eeration.nextElement();
cellFrame.width += aColumn.getWidth() + columnMargin;
}
if (!includeSpacing) {
Dimension spacing = getIntercellSpacing();
cellFrame.setBounds(cellFrame.x + spacing.width/2,
cellFrame.y + spacing.height/2,
cellFrame.width - spacing.width,
cellFrame.height - spacing.height);
}
return cellFrame;
}
private int[] rowColumnAtPoint(Point point) {
int[] retValue = {-1,-1};
int row = point.y / (rowHeight + rowMargin);
if ((row <0)||(getRowCount() <= row)) return retValue;
int column = getColumnModel().getColumnIndexAtX(point.x);
CellSpan cellAtt = (CellSpan)((AttributiveCellTableModel)getModel()).getCellAttribute();
if (cellAtt.isVisible(row,column)) {
retValue[CellSpan.COLUMN] = column;
retValue[CellSpan.ROW ] = row;
return retValue;
}
retValue[CellSpan.COLUMN] = column + cellAtt.getSpan(row,column)[CellSpan.COLUMN];
retValue[CellSpan.ROW ] = row + cellAtt.getSpan(row,column)[CellSpan.ROW];
return retValue;
}
public int rowAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.ROW];
}
public int columnAtPoint(Point point) {
return rowColumnAtPoint(point)[CellSpan.COLUMN];
}
public void columnSelectionChanged(ListSelectionEvent e) {
repaint();
}
public void valueChanged(ListSelectionEvent e) {
int firstIndex = e.getFirstIndex();
int lastIndex = e.getLastIndex();
if (firstIndex == -1 && lastIndex == -1) { // Selection cleared.
repaint();
}
Rectangle dirtyRegion = getCellRect(firstIndex, 0, false);
int numCoumns = getColumnCount();
int index = firstIndex;
for (int i=0;i<numCoumns;i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
index = lastIndex;
for (int i=0;i<numCoumns;i++) {
dirtyRegion.add(getCellRect(index, i, false));
}
repaint(dirtyRegion.x, dirtyRegion.y, dirtyRegion.width, dirtyRegion.height);
}
}
/**
* @version 1.0 11/26/98
*/
class MultiSpanCellTableUI extends BasicTableUI {
public void paint(Graphics g, JComponent c) {
Rectangle oldClipBounds = g.getClipBounds();
Rectangle clipBounds = new Rectangle(oldClipBounds);
int tableWidth = table.getColumnModel().getTotalColumnWidth();
clipBounds.width = Math.min(clipBounds.width, tableWidth);
g.setClip(clipBounds);
int firstIndex = table.rowAtPoint(new Point(0, clipBounds.y));
int lastIndex = table.getRowCount()-1;
Rectangle rowRect = new Rectangle(0,0,
tableWidth, table.getRowHeight() + table.getRowMargin());
rowRect.y = firstIndex*rowRect.height;
for (int index = firstIndex; index <= lastIndex; index++) {
if (rowRect.intersects(clipBounds)) {
//System.out.println(); // debug
//System.out.print("" + index +": "); // row
paintRow(g, index);
}
rowRect.y += rowRect.height;
}
g.setClip(oldClipBounds);
}
private void paintRow(Graphics g, int row) {
Rectangle rect = g.getClipBounds();
boolean drawn = false;
AttributiveCellTableModel tableModel = (AttributiveCellTableModel)table.getModel();
CellSpan cellAtt = (CellSpan)tableModel.getCellAttribute();
int numColumns = table.getColumnCount();
for (int column = 0; column < numColumns; column++) {
Rectangle cellRect = table.getCellRect(row,column,true);
int cellRow,cellColumn;
if (cellAtt.isVisible(row,column)) {
cellRow = row;
cellColumn = column;
// System.out.print(" "+column+" "); // debug
} else {
cellRow = row + cellAtt.getSpan(row,column)[CellSpan.ROW];
cellColumn = column + cellAtt.getSpan(row,column)[CellSpan.COLUMN];
// System.out.print(" ("+column+")"); // debug
}
if (cellRect.intersects(rect)) {
drawn = true;
paintCell(g, cellRect, cellRow, cellColumn);
} else {
if (drawn) break;
}
}
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
int spacingHeight = table.getRowMargin();
int spacingWidth = table.getColumnModel().getColumnMargin();
Color c = g.getColor();
g.setColor(table.getGridColor());
g.drawRect(cellRect.x,cellRect.y,cellRect.width-1,cellRect.height-1);
g.setColor(c);
cellRect.setBounds(cellRect.x + spacingWidth/2, cellRect.y + spacingHeight/2,
cellRect.width - spacingWidth, cellRect.height - spacingHeight);
if (table.isEditing() && table.getEditingRow()==row &&
table.getEditingColumn()==column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
}
else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if (component.getParent() == null) {
rendererPane.add(component);
}
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
}
}
interface CellFont {
public Font getFont(int row, int column);
public void setFont(Font font, int row, int column);
public void setFont(Font font, int[] rows, int[] columns);
}
interface ColoredCell {
public Color getForeground(int row, int column);
public void setForeground(Color color, int row, int column);
public void setForeground(Color color, int[] rows, int[] columns);
public Color getBackground(int row, int column);
public void setBackground(Color color, int row, int column);
public void setBackground(Color color, int[] rows, int[] columns);
}
MultiWidth Header Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
* (swing1.1beta3)
*
* |-----------------------------------------------------|
* | 1st | 2nd | 3rd |
* |-----------------------------------------------------|
* | | | | | | |
*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* @version 1.0 11/09/98
*/
public class MultiWidthHeaderExample extends JFrame {
MultiWidthHeaderExample() {
super( "Multi-Width Header Example" );
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][]{
{"a","b","c","d","e","f"},
{"A","B","C","D","E","F"}},
new Object[]{"1 st","","","","",""});
JTable table = new JTable( dm ) {
protected JTableHeader createDefaultTableHeader() {
return new GroupableTableHeader(columnModel);
}
};
TableColumnModel cm = table.getColumnModel();
ColumnGroup g_2nd = new ColumnGroup("2 nd");
g_2nd.add(cm.getColumn(1));
g_2nd.add(cm.getColumn(2));
ColumnGroup g_3rd = new ColumnGroup("3 rd");
g_3rd.add(cm.getColumn(3));
g_3rd.add(cm.getColumn(4));
g_3rd.add(cm.getColumn(5));
GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
header.addColumnGroup(g_2nd);
header.addColumnGroup(g_3rd);
JScrollPane scroll = new JScrollPane( table );
getContentPane().add( scroll );
setSize( 400, 100 );
header.revalidate();
}
public static void main(String[] args) {
MultiWidthHeaderExample frame = new MultiWidthHeaderExample();
frame.addWindowListener( new WindowAdapter() {
public void windowClosing( WindowEvent e ) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
/*
* (swing1.1beta3)
*
*/
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* ColumnGroup
*
* @version 1.0 10/20/98
* @author Nobuo Tamemasa
*/
public class ColumnGroup {
protected TableCellRenderer renderer;
protected Vector v;
protected String text;
protected int margin=0;
public ColumnGroup(String text) {
this(null,text);
}
public ColumnGroup(TableCellRenderer renderer,String text) {
if (renderer == null) {
this.renderer = new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JTableHeader header = table.getTableHeader();
if (header != null) {
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
setHorizontalAlignment(JLabel.CENTER);
setText((value == null) ? "" : value.toString());
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return this;
}
};
} else {
this.renderer = renderer;
}
this.text = text;
v = new Vector();
}
/**
* @param obj TableColumn or ColumnGroup
*/
public void add(Object obj) {
if (obj == null) { return; }
v.addElement(obj);
}
/**
* @param c TableColumn
* @param v ColumnGroups
*/
public Vector getColumnGroups(TableColumn c, Vector g) {
g.addElement(this);
if (v.contains(c)) return g;
Enumeration e = v.elements();
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof ColumnGroup) {
Vector groups =
(Vector)((ColumnGroup)obj).getColumnGroups(c,(Vector)g.clone());
if (groups != null) return groups;
}
}
return null;
}
public TableCellRenderer getHeaderRenderer() {
return renderer;
}
public void setHeaderRenderer(TableCellRenderer renderer) {
if (renderer != null) {
this.renderer = renderer;
}
}
public Object getHeaderValue() {
return text;
}
public Dimension getSize(JTable table) {
Component comp = renderer.getTableCellRendererComponent(
table, getHeaderValue(), false, false,-1, -1);
int height = comp.getPreferredSize().height;
int width = 0;
Enumeration e = v.elements();
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof TableColumn) {
TableColumn aColumn = (TableColumn)obj;
width += aColumn.getWidth();
width += margin;
} else {
width += ((ColumnGroup)obj).getSize(table).width;
}
}
return new Dimension(width, height);
}
public void setColumnMargin(int margin) {
this.margin = margin;
Enumeration e = v.elements();
while (e.hasMoreElements()) {
Object obj = e.nextElement();
if (obj instanceof ColumnGroup) {
((ColumnGroup)obj).setColumnMargin(margin);
}
}
}
}
/*
* (swing1.1beta3)
*
*/
import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
/**
* GroupableTableHeader
*
* @version 1.0 10/20/98
* @author Nobuo Tamemasa
*/
public class GroupableTableHeader extends JTableHeader {
private static final String uiClassID = "GroupableTableHeaderUI";
protected Vector columnGroups = null;
public GroupableTableHeader(TableColumnModel model) {
super(model);
setUI(new GroupableTableHeaderUI());
setReorderingAllowed(false);
}
public void updateUI(){
setUI(new GroupableTableHeaderUI());
}
public void setReorderingAllowed(boolean b) {
reorderingAllowed = false;
}
public void addColumnGroup(ColumnGroup g) {
if (columnGroups == null) {
columnGroups = new Vector();
}
columnGroups.addElement(g);
}
public Enumeration getColumnGroups(TableColumn col) {
if (columnGroups == null) return null;
Enumeration e = columnGroups.elements();
while (e.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)e.nextElement();
Vector v_ret = (Vector)cGroup.getColumnGroups(col,new Vector());
if (v_ret != null) {
return v_ret.elements();
}
}
return null;
}
public void setColumnMargin() {
if (columnGroups == null) return;
int columnMargin = getColumnModel().getColumnMargin();
Enumeration e = columnGroups.elements();
while (e.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)e.nextElement();
cGroup.setColumnMargin(columnMargin);
}
}
}
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.BasicTableHeaderUI;
public class GroupableTableHeaderUI extends BasicTableHeaderUI {
public void paint(Graphics g, JComponent c) {
Rectangle clipBounds = g.getClipBounds();
if (header.getColumnModel() == null) return;
((GroupableTableHeader)header).setColumnMargin();
int column = 0;
Dimension size = header.getSize();
Rectangle cellRect = new Rectangle(0, 0, size.width, size.height);
Hashtable h = new Hashtable();
int columnMargin = header.getColumnModel().getColumnMargin();
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
cellRect.height = size.height;
cellRect.y = 0;
TableColumn aColumn = (TableColumn)enumeration.nextElement();
Enumeration cGroups = ((GroupableTableHeader)header).getColumnGroups(aColumn);
if (cGroups != null) {
int groupHeight = 0;
while (cGroups.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)cGroups.nextElement();
Rectangle groupRect = (Rectangle)h.get(cGroup);
if (groupRect == null) {
groupRect = new Rectangle(cellRect);
Dimension d = cGroup.getSize(header.getTable());
groupRect.width = d.width;
groupRect.height = d.height;
h.put(cGroup, groupRect);
}
paintCell(g, groupRect, cGroup);
groupHeight += groupRect.height;
cellRect.height = size.height - groupHeight;
cellRect.y = groupHeight;
}
}
cellRect.width = aColumn.getWidth() + columnMargin;
if (cellRect.intersects(clipBounds)) {
paintCell(g, cellRect, column);
}
cellRect.x += cellRect.width;
column++;
}
}
private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
TableCellRenderer renderer = aColumn.getHeaderRenderer();
//revised by jexp.ru
renderer = new DefaultTableCellRenderer(){
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel header = new JLabel();
header.setForeground(table.getTableHeader().getForeground());
header.setBackground(table.getTableHeader().getBackground());
header.setFont(table.getTableHeader().getFont());
header.setHorizontalAlignment(JLabel.CENTER);
header.setText(value.toString());
header.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
return header;
}
};
Component c = renderer.getTableCellRendererComponent(
header.getTable(), aColumn.getHeaderValue(),false, false, -1, columnIndex);
rendererPane.add(c);
rendererPane.paintComponent(g, c, header, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
private void paintCell(Graphics g, Rectangle cellRect,ColumnGroup cGroup) {
TableCellRenderer renderer = cGroup.getHeaderRenderer();
//revised by jexp.ru
// if(renderer == null){
// return ;
// }
Component component = renderer.getTableCellRendererComponent(
header.getTable(), cGroup.getHeaderValue(),false, false, -1, -1);
rendererPane.add(component);
rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
private int getHeaderHeight() {
int height = 0;
TableColumnModel columnModel = header.getColumnModel();
for(int column = 0; column < columnModel.getColumnCount(); column++) {
TableColumn aColumn = columnModel.getColumn(column);
TableCellRenderer renderer = aColumn.getHeaderRenderer();
//revised by jexp.ru
if(renderer == null){
return 16;
}
Component comp = renderer.getTableCellRendererComponent(
header.getTable(), aColumn.getHeaderValue(), false, false,-1, column);
int cHeight = comp.getPreferredSize().height;
Enumeration e = ((GroupableTableHeader)header).getColumnGroups(aColumn);
if (e != null) {
while (e.hasMoreElements()) {
ColumnGroup cGroup = (ColumnGroup)e.nextElement();
cHeight += cGroup.getSize(header.getTable()).height;
}
}
height = Math.max(height, cHeight);
}
return height;
}
private Dimension createHeaderSize(long width) {
TableColumnModel columnModel = header.getColumnModel();
width += columnModel.getColumnMargin() * columnModel.getColumnCount();
if (width > Integer.MAX_VALUE) {
width = Integer.MAX_VALUE;
}
return new Dimension((int)width, getHeaderHeight());
}
public Dimension getPreferredSize(JComponent c) {
long width = 0;
Enumeration enumeration = header.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getPreferredWidth();
}
return createHeaderSize(width);
}
}
Pushable Table Header Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/**
* @version 1.0 02/25/99
*/
public class PushableHeaderExample extends JPanel {
public PushableHeaderExample() {
setLayout(new BorderLayout());
String[] headerStr = { "Push", "me", "here" };
DefaultTableModel dm = new DefaultTableModel(headerStr, 4);
JTable table = new JTable(dm);
ButtonHeaderRenderer renderer = new ButtonHeaderRenderer();
TableColumnModel model = table.getColumnModel();
int n = headerStr.length;
for (int i = 0; i < n; i++) {
model.getColumn(i).setHeaderRenderer(renderer);
}
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("PushableHeaderTable Example");
f.getContentPane()
.add(new PushableHeaderExample(), BorderLayout.CENTER);
f.setSize(400, 100);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
class HeaderListener extends MouseAdapter {
JTableHeader header;
ButtonHeaderRenderer renderer;
HeaderListener(JTableHeader header, ButtonHeaderRenderer renderer) {
this.header = header;
this.renderer = renderer;
}
public void mousePressed(MouseEvent e) {
int col = header.columnAtPoint(e.getPoint());
renderer.setPressedColumn(col);
header.repaint();
System.out.println("Ouch! " + col);
}
public void mouseReleased(MouseEvent e) {
int col = header.columnAtPoint(e.getPoint());
renderer.setPressedColumn(-1); // clear
header.repaint();
}
}
class ButtonHeaderRenderer extends JButton implements TableCellRenderer {
int pushedColumn;
public ButtonHeaderRenderer() {
pushedColumn = -1;
setMargin(new Insets(0, 0, 0, 0));
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
setText((value == null) ? "" : value.toString());
boolean isPressed = (column == pushedColumn);
getModel().setPressed(isPressed);
getModel().setArmed(isPressed);
return this;
}
public void setPressedColumn(int col) {
pushedColumn = col;
}
}
}
Radio Button Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/**
* @version 1.0 12/03/98
*/
import java.awt.ruponent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ButtonGroup;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
class RadioButtonRenderer implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null)
return null;
return (Component) value;
}
}
class RadioButtonEditor extends DefaultCellEditor implements ItemListener {
private JRadioButton button;
public RadioButtonEditor(JCheckBox checkBox) {
super(checkBox);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (value == null)
return null;
button = (JRadioButton) value;
button.addItemListener(this);
return (Component) value;
}
public Object getCellEditorValue() {
button.removeItemListener(this);
return button;
}
public void itemStateChanged(ItemEvent e) {
super.fireEditingStopped();
}
}
public class JRadioButtonTableExample extends JFrame {
public JRadioButtonTableExample() {
super("JRadioButtonTable Example");
UIDefaults ui = UIManager.getLookAndFeel().getDefaults();
UIManager.put("RadioButton.focus", ui.getColor("control"));
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][] { { "Group 1", new JRadioButton("A") },
{ "Group 1", new JRadioButton("B") },
{ "Group 1", new JRadioButton("C") },
{ "Group 2", new JRadioButton("a") },
{ "Group 2", new JRadioButton("b") } }, new Object[] {
"String", "JRadioButton" });
JTable table = new JTable(dm) {
public void tableChanged(TableModelEvent e) {
super.tableChanged(e);
repaint();
}
};
ButtonGroup group1 = new ButtonGroup();
group1.add((JRadioButton) dm.getValueAt(0, 1));
group1.add((JRadioButton) dm.getValueAt(1, 1));
group1.add((JRadioButton) dm.getValueAt(2, 1));
ButtonGroup group2 = new ButtonGroup();
group2.add((JRadioButton) dm.getValueAt(3, 1));
group2.add((JRadioButton) dm.getValueAt(4, 1));
table.getColumn("JRadioButton").setCellRenderer(
new RadioButtonRenderer());
table.getColumn("JRadioButton").setCellEditor(
new RadioButtonEditor(new JCheckBox()));
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
setSize(200, 140);
setVisible(true);
}
public static void main(String[] args) {
JRadioButtonTableExample frame = new JRadioButtonTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
RadioButton Table Example 2
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1.1) */
import java.awt.ruponent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
* @version 1.2 08/13/99
*/
public class JRadioButtonTableExample2 extends JFrame {
public JRadioButtonTableExample2() {
super("JRadioButtonTable Example");
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][] { { "1", new Integer(-1) },
{ "2", new Integer(-1) }, { "3", new Integer(0) },
{ "4", new Integer(1) }, { "5", new Integer(2) } },
new Object[] { "Question", "Answer" });
JTable table = new JTable(dm);
String[] answer = { "A", "B", "C" };
table.getColumn("Answer").setCellRenderer(
new RadioButtonRenderer(answer));
table.getColumn("Answer").setCellEditor(
new RadioButtonEditor(new JCheckBox(), new RadioButtonPanel(
answer)));
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
}
// Cell base
class RadioButtonPanel extends JPanel {
JRadioButton[] buttons;
RadioButtonPanel(String[] str) {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
buttons = new JRadioButton[str.length];
for (int i = 0; i < buttons.length; i++) {
buttons[i] = new JRadioButton(str[i]);
buttons[i].setFocusPainted(false);
add(buttons[i]);
}
}
public void setSelectedIndex(int index) {
for (int i = 0; i < buttons.length; i++) {
buttons[i].setSelected(i == index);
}
}
public int getSelectedIndex() {
for (int i = 0; i < buttons.length; i++) {
if (buttons[i].isSelected()) {
return i;
}
}
return -1;
}
public JRadioButton[] getButtons() {
return buttons;
}
}
class RadioButtonRenderer extends RadioButtonPanel implements
TableCellRenderer {
RadioButtonRenderer(String[] strs) {
super(strs);
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
if (value instanceof Integer) {
setSelectedIndex(((Integer) value).intValue());
}
return this;
}
}
class RadioButtonEditor extends DefaultCellEditor implements ItemListener {
RadioButtonPanel panel;
public RadioButtonEditor(JCheckBox checkBox, RadioButtonPanel panel) {
super(checkBox);
this.panel = panel;
ButtonGroup buttonGroup = new ButtonGroup();
JRadioButton[] buttons = panel.getButtons();
for (int i = 0; i < buttons.length; i++) {
buttonGroup.add(buttons[i]);
buttons[i].addItemListener(this);
}
}
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column) {
if (value instanceof Integer) {
panel.setSelectedIndex(((Integer) value).intValue());
}
return panel;
}
public Object getCellEditorValue() {
return new Integer(panel.getSelectedIndex());
}
public void itemStateChanged(ItemEvent e) {
super.fireEditingStopped();
}
}
public static void main(String[] args) {
JRadioButtonTableExample2 frame = new JRadioButtonTableExample2();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setSize(230, 140);
frame.setVisible(true);
}
}
Sortable Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.Hashtable;
import java.util.Locale;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
/**
* @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();
}
}
}
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;
}
}
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).rupareTo((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).rupareTo((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;
}
}
}
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;
}
}
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);
}
}
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;
}
}
Striped Currency Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class StripedCurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Striped Currency Table");
JTable tbl = new JTable(new CurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tbl.setShowHorizontalLines(false);
// Add the stripe renderer.
StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
Color.white, null, null);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon)value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
Swing Table in ComboBox
(From http://swinglabs.org/downloads.jsp)
Tabbable Currency Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.EventObject;
import java.util.Vector;
import javax.swing.CellEditor;
import javax.swing.FocusManager;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.event.TableColumnModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
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;
public class TabbableCurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Tabbable Currency Table");
TabEditTable tbl = new TabEditTable(
new TestUpdatableCurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tbl.setShowHorizontalLines(false);
tbl.setIntercellSpacing(new Dimension(1, 0));
// Add the stripe renderer in the leftmost four columns.
StripedTableCellRenderer.installInColumn(tbl, 0, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 1, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 2, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 3, Color.lightGray,
Color.white, null, null);
// Add the highlight renderer to the difference column.
// The following comparator makes it highlight
// cells with negative numeric values.
Comparator cmp = new Comparator() {
public boolean shouldHighlight(JTable tbl, Object value, int row,
int column) {
if (value instanceof Number) {
double columnValue = ((Number) value).doubleValue();
return columnValue < (double) 0.0;
}
return false;
}
};
tcm.getColumn(3).setCellRenderer(
new HighlightRenderer(cmp, null, Color.pink, Color.black,
Color.pink.darker(), Color.white));
// Install a button renderer in the last column
ButtonRenderer buttonRenderer = new ButtonRenderer();
buttonRenderer.setForeground(Color.blue);
buttonRenderer.setBackground(Color.lightGray);
tcm.getColumn(4).setCellRenderer(buttonRenderer);
// Install a button editor in the last column
TableCellEditor editor = new ButtonEditor(new JButton());
tcm.getColumn(4).setCellEditor(editor);
// Install the list of columns containing tabbable editors
tbl.setEditingColumns(new int[] { 1, 2 });
// Make the rows wide enough to take the buttons
tbl.setRowHeight(20);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class TabEditTable extends JTable {
public TabEditTable() {
super();
}
public TabEditTable(TableModel dm) {
super(dm);
}
public TabEditTable(TableModel dm, TableColumnModel cm) {
super(dm, cm);
}
public TabEditTable(TableModel dm, TableColumnModel cm,
ListSelectionModel sm) {
super(dm, cm, sm);
}
public TabEditTable(int numRows, int numColumns) {
super(numRows, numColumns);
}
public TabEditTable(final Vector rowData, final Vector columnNames) {
super(rowData, columnNames);
}
public TabEditTable(final Object[][] rowData, final Object[] columnNames) {
super(rowData, columnNames);
}
// Set the columns that contain tabbable editors
public void setEditingColumns(int[] columns) {
editingColumns = columns;
convertEditableColumnsToView();
}
public int[] getEditingColumns() {
return editingColumns;
}
// Overrides of JTable methods
public boolean editCellAt(int row, int column, EventObject evt) {
if (super.editCellAt(row, column, evt) == false) {
return false;
}
if (viewEditingColumns != null) {
// Note: column is specified in terms of the column model
int length = viewEditingColumns.length;
for (int i = 0; i < length; i++) {
if (column == viewEditingColumns[i]) {
Component comp = getEditorComponent();
comp.addKeyListener(tabKeyListener);
this.addKeyListener(tabKeyListener);
focusManager = FocusManager.getCurrentManager();
FocusManager.disableSwingFocusManager();
inTabbingEditor = true;
comp.requestFocus();
break;
}
}
}
return true;
}
public void editingStopped(ChangeEvent evt) {
if (inTabbingEditor == true) {
Component comp = getEditorComponent();
comp.removeKeyListener(tabKeyListener);
this.removeKeyListener(tabKeyListener);
FocusManager.setCurrentManager(focusManager);
inTabbingEditor = false;
}
super.editingStopped(evt);
}
protected void convertEditableColumnsToView() {
// Convert the editable columns to view column numbers
if (editingColumns == null) {
viewEditingColumns = null;
return;
}
// Create a set of editable columns in terms of view
// column numbers in ascending order. Note that not all
// editable columns in the data model need be visible.
int length = editingColumns.length;
viewEditingColumns = new int[length];
int nextSlot = 0;
for (int i = 0; i < length; i++) {
int viewIndex = convertColumnIndexToView(editingColumns[i]);
if (viewIndex != -1) {
viewEditingColumns[nextSlot++] = viewIndex;
}
}
// Now create an array of the right length to hold the view indices
if (nextSlot < length) {
int[] tempArray = new int[nextSlot];
System.arraycopy(viewEditingColumns, 0, tempArray, 0, nextSlot);
viewEditingColumns = tempArray;
}
// Finally, sort the view columns into order
TableUtilities.sort(viewEditingColumns);
}
protected void moveToNextEditor(int row, int column, boolean forward) {
// Column is specified in terms of the column model
if (viewEditingColumns != null) {
int length = viewEditingColumns.length;
// Move left-to-right or right-to-left across the table
for (int i = 0; i < length; i++) {
if (viewEditingColumns[i] == column) {
// Select the next column to edit
if (forward == true) {
if (++i == length) {
// Reached end of row - wrap
i = 0;
row++;
if (row == getRowCount()) {
// End of table - wrap
row = 0;
}
}
} else {
if (--i < 0) {
i = length - 1;
row--;
if (row < 0) {
row = getRowCount() - 1;
}
}
}
final int newRow = row;
final int newColumn = viewEditingColumns[i];
// Start editing at new location
SwingUtilities.invokeLater(new Runnable() {
public void run() {
editCellAt(newRow, newColumn);
ListSelectionModel rowSel = getSelectionModel();
ListSelectionModel columnSel = getColumnModel()
.getSelectionModel();
rowSel.setSelectionInterval(newRow, newRow);
columnSel
.setSelectionInterval(newColumn, newColumn);
}
});
break;
}
}
}
}
// Catch changes to the table column model
public void columnAdded(TableColumnModelEvent e) {
super.columnAdded(e);
convertEditableColumnsToView();
}
public void columnRemoved(TableColumnModelEvent e) {
super.columnRemoved(e);
convertEditableColumnsToView();
}
public void columnMoved(TableColumnModelEvent e) {
super.columnMoved(e);
convertEditableColumnsToView();
}
public class TabKeyListener extends KeyAdapter {
public void keyPressed(KeyEvent evt) {
if (evt.getKeyCode() == KeyEvent.VK_TAB) {
if (inTabbingEditor == true) {
TableCellEditor editor = getCellEditor();
int editRow = getEditingRow();
int editColumn = getEditingColumn();
if (editor != null) {
boolean stopped = editor.stopCellEditing();
if (stopped == true) {
boolean forward = (evt.isShiftDown() == false);
moveToNextEditor(editRow, editColumn, forward);
}
}
}
}
}
}
protected boolean inTabbingEditor;
protected FocusManager focusManager;
protected int[] editingColumns; // Model columns
protected int[] viewEditingColumns; // View columns
protected TabKeyListener tabKeyListener = new TabKeyListener();
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class TableUtilities {
// Calculate the required width of a table column
public static int calculateColumnWidth(JTable table, int columnIndex) {
int width = 0; // The return value
int rowCount = table.getRowCount();
for (int i = 0; i < rowCount; i++) {
TableCellRenderer renderer = table.getCellRenderer(i, columnIndex);
Component comp = renderer.getTableCellRendererComponent(table,
table.getValueAt(i, columnIndex), false, false, i,
columnIndex);
int thisWidth = comp.getPreferredSize().width;
if (thisWidth > width) {
width = thisWidth;
}
}
return width;
}
// Set the widths of every column in a table
public static void setColumnWidths(JTable table, Insets insets,
boolean setMinimum, boolean setMaximum) {
int columnCount = table.getColumnCount();
TableColumnModel tcm = table.getColumnModel();
int spare = (insets == null ? 0 : insets.left + insets.right);
for (int i = 0; i < columnCount; i++) {
int width = calculateColumnWidth(table, i);
width += spare;
TableColumn column = tcm.getColumn(i);
column.setPreferredWidth(width);
if (setMinimum == true) {
column.setMinWidth(width);
}
if (setMaximum == true) {
column.setMaxWidth(width);
}
}
}
// Sort an array of integers in place
public static void sort(int[] values) {
int length = values.length;
if (length > 1) {
for (int i = 0; i < length - 1; i++) {
for (int j = i + 1; j < length; j++) {
if (values[j] < values[i]) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
}
}
}
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
class HighlightRenderer implements TableCellRenderer {
public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
Color backColor, Color foreColor, Color highlightBack,
Color highlightFore) {
this.cmp = cmp;
this.targetRenderer = targetRenderer;
this.backColor = backColor;
this.foreColor = foreColor;
this.highlightBack = highlightBack;
this.highlightFore = highlightFore;
}
public Component getTableCellRendererComponent(JTable tbl, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
}
Component comp = renderer.getTableCellRendererComponent(tbl, value,
isSelected, hasFocus, row, column);
if (isSelected == false && hasFocus == false && value != null) {
if (cmp.shouldHighlight(tbl, value, row, column)) {
comp.setForeground(highlightFore);
comp.setBackground(highlightBack);
} else {
comp.setForeground(foreColor);
comp.setBackground(backColor);
}
}
return comp;
}
protected Comparator cmp;
protected TableCellRenderer targetRenderer;
protected Color backColor;
protected Color foreColor;
protected Color highlightBack;
protected Color highlightFore;
}
interface Comparator {
public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
int column);
}
class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
this.border = getBorder();
this.setOpaque(true);
}
public void setForeground(Color foreground) {
this.foreground = foreground;
super.setForeground(foreground);
}
public void setBackground(Color background) {
this.background = background;
super.setBackground(background);
}
public void setFont(Font font) {
this.font = font;
super.setFont(font);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Color cellForeground = foreground != null ? foreground : table
.getForeground();
Color cellBackground = background != null ? background : table
.getBackground();
setFont(font != null ? font : table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
cellForeground = UIManager
.getColor("Table.focusCellForeground");
cellBackground = UIManager
.getColor("Table.focusCellBackground");
}
} else {
setBorder(border);
}
super.setForeground(cellForeground);
super.setBackground(cellBackground);
// Customize the component"s appearance
setValue(value);
return this;
}
protected void setValue(Object value) {
if (value == null) {
setText("");
setIcon(null);
} else if (value instanceof Icon) {
setText("");
setIcon((Icon) value);
} else if (value instanceof DataWithIcon) {
DataWithIcon d = (DataWithIcon) value;
setText(d.toString());
setIcon(d.getIcon());
} else {
setText(value.toString());
setIcon(null);
}
}
protected Color foreground;
protected Color background;
protected Font font;
protected Border border;
}
class ButtonEditor extends BasicCellEditor implements ActionListener,
TableCellEditor {
public ButtonEditor(JButton button) {
super(button);
button.addActionListener(this);
}
public void setForeground(Color foreground) {
this.foreground = foreground;
editor.setForeground(foreground);
}
public void setBackground(Color background) {
this.background = background;
editor.setBackground(background);
}
public void setFont(Font font) {
this.font = font;
editor.setFont(font);
}
public Object getCellEditorValue() {
return value;
}
public void editingStarted(EventObject event) {
// Edit starting - click the button if necessary
if (!(event instanceof MouseEvent)) {
// Keyboard event - click the button
SwingUtilities.invokeLater(new Runnable() {
public void run() {
((JButton) editor).doClick();
}
});
}
}
public Component getTableCellEditorComponent(JTable tbl, Object value,
boolean isSelected, int row, int column) {
editor.setForeground(foreground != null ? foreground : tbl
.getForeground());
editor.setBackground(background != null ? background : tbl
.getBackground());
editor.setFont(font != null ? font : tbl.getFont());
this.value = value;
setValue(value);
return editor;
}
protected void setValue(Object value) {
JButton button = (JButton) editor;
if (value == null) {
button.setText("");
button.setIcon(null);
} else if (value instanceof Icon) {
button.setText("");
button.setIcon((Icon) value);
} else if (value instanceof DataWithIcon) {
DataWithIcon d = (DataWithIcon) value;
button.setText(d.toString());
button.setIcon(d.getIcon());
} else {
button.setText(value.toString());
button.setIcon(null);
}
}
public void actionPerformed(ActionEvent evt) {
// Button pressed - stop the edit
stopCellEditing();
}
protected Object value;
protected Color foreground;
protected Color background;
protected Font font;
}
class BasicCellEditor implements CellEditor, PropertyChangeListener {
public BasicCellEditor() {
this.editor = null;
}
public BasicCellEditor(JComponent editor) {
this.editor = editor;
editor.addPropertyChangeListener(this);
}
public Object getCellEditorValue() {
return null;
}
public boolean isCellEditable(EventObject evt) {
editingEvent = evt;
return true;
}
public boolean shouldSelectCell(EventObject evt) {
return true;
}
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
public void cancelCellEditing() {
fireEditingCanceled();
}
public void addCellEditorListener(CellEditorListener l) {
listeners.add(CellEditorListener.class, l);
}
public void removeCellEditorListener(CellEditorListener l) {
listeners.remove(CellEditorListener.class, l);
}
// Returns the editing component
public JComponent getComponent() {
return editor;
}
// Sets the editing component
public void setComponent(JComponent comp) {
editor = comp;
}
// Returns the event that triggered the edit
public EventObject getEditingEvent() {
return editingEvent;
}
// Method invoked when the editor is installed in the table.
// Overridden in derived classes to take any convenient
// action.
public void editingStarted(EventObject event) {
}
protected void fireEditingStopped() {
Object[] l = listeners.getListenerList();
for (int i = l.length - 2; i >= 0; i -= 2) {
if (l[i] == CellEditorListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((CellEditorListener) l[i + 1]).editingStopped(changeEvent);
}
}
}
protected void fireEditingCanceled() {
Object[] l = listeners.getListenerList();
for (int i = l.length - 2; i >= 0; i -= 2) {
if (l[i] == CellEditorListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((CellEditorListener) l[i + 1]).editingCanceled(changeEvent);
}
}
}
// Implementation of the PropertyChangeListener interface
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("ancestor")
&& evt.getNewValue() != null) {
// Added to table - notify the editor
editingStarted(editingEvent);
}
}
protected static JCheckBox checkBox = new JCheckBox();
protected static ChangeEvent changeEvent;
protected JComponent editor;
protected EventListenerList listeners = new EventListenerList();
protected EventObject editingEvent;
}
class TestUpdatableCurrencyTableModel extends UpdatableCurrencyTableModel {
public void updateTable(Object value, int row, int column) {
System.out.println("Update for row " + row + " required.");
System.out.println("Values are " + getValueAt(row, 1) + ", "
+ getValueAt(row, 2) + "; diff is " + getValueAt(row, 3));
}
}
abstract class UpdatableCurrencyTableModel extends EditableCurrencyTableModel {
public int getColumnCount() {
return super.getColumnCount() + 1;
}
public Object getValueAt(int row, int column) {
if (column == BUTTON_COLUMN) {
return "Update";
}
return super.getValueAt(row, column);
}
public Class getColumnClass(int column) {
if (column == BUTTON_COLUMN) {
return String.class;
}
return super.getColumnClass(column);
}
public String getColumnName(int column) {
if (column == BUTTON_COLUMN) {
return "";
}
return super.getColumnName(column);
}
public boolean isCellEditable(int row, int column) {
return column == BUTTON_COLUMN || super.isCellEditable(row, column);
}
public void setValueAt(Object value, int row, int column) {
if (column == BUTTON_COLUMN) {
// Button press - do whatever is needed to update the table source
updateTable(value, row, column);
return;
}
// Other columns - use superclass
super.setValueAt(value, row, column);
}
// Used to implement the table update
protected abstract void updateTable(Object value, int row, int column);
protected static final int BUTTON_COLUMN = 4;
}
class EditableCurrencyTableModel extends CurrencyTableModel {
public boolean isCellEditable(int row, int column) {
return column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN;
}
public void setValueAt(Object value, int row, int column) {
try {
if (column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN) {
Double newObjectValue; // New value as an Object
double newValue; // double, for validity checking
if (value instanceof Number) {
// Convert Number to Double
newValue = ((Number) value).doubleValue();
newObjectValue = new Double(newValue);
} else if (value instanceof String) {
// Convert a String to a Double
newObjectValue = new Double((String) value);
newValue = newObjectValue.doubleValue();
} else {
// Unrecognized - ignore
return;
}
if (newValue > (double) 0.0) {
// Store new value, but reject zero or negative values
data[row][column] = newObjectValue;
data[row][DIFF_COLUMN] = new Double(
((Double) data[row][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[row][OLD_RATE_COLUMN])
.doubleValue());
fireTableRowsUpdated(row, row);
}
}
} catch (NumberFormatException e) {
// Ignore a badly-formatted number
}
}
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))),
new Double(0.6213051), new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
Table Row Header Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.BorderLayout;
import java.awt.ruponent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
/**
* @version 1.0 11/09/98
*/
class RowHeaderRenderer extends JLabel implements ListCellRenderer {
RowHeaderRenderer(JTable table) {
JTableHeader header = table.getTableHeader();
setOpaque(true);
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(CENTER);
setForeground(header.getForeground());
setBackground(header.getBackground());
setFont(header.getFont());
}
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
setText((value == null) ? "" : value.toString());
return this;
}
}
public class RowHeaderExample extends JFrame {
public RowHeaderExample() {
super("Row Header Example");
setSize(300, 150);
ListModel lm = new AbstractListModel() {
String headers[] = { "a", "b", "c", "d", "e", "f", "g", "h", "i" };
public int getSize() {
return headers.length;
}
public Object getElementAt(int index) {
return headers[index];
}
};
DefaultTableModel dm = new DefaultTableModel(lm.getSize(), 10);
JTable table = new JTable(dm);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
JList rowHeader = new JList(lm);
rowHeader.setFixedCellWidth(50);
rowHeader.setFixedCellHeight(table.getRowHeight()
+ table.getRowMargin());
// + table.getIntercellSpacing().height);
rowHeader.setCellRenderer(new RowHeaderRenderer(table));
JScrollPane scroll = new JScrollPane(table);
scroll.setRowHeaderView(rowHeader);
getContentPane().add(scroll, BorderLayout.CENTER);
}
public static void main(String[] args) {
RowHeaderExample frame = new RowHeaderExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
Table Utilities
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class TableUtilities {
// Calculate the required width of a table column
public static int calculateColumnWidth(JTable table,
int columnIndex) {
int width = 0; // The return value
int rowCount = table.getRowCount();
for (int i = 0; i < rowCount ; i++) {
TableCellRenderer renderer = table.getCellRenderer(i, columnIndex);
Component comp = renderer.getTableCellRendererComponent(
table, table.getValueAt(i, columnIndex),
false, false, i, columnIndex);
int thisWidth = comp.getPreferredSize().width;
if (thisWidth > width) {
width = thisWidth;
}
}
return width;
}
// Set the widths of every column in a table
public static void setColumnWidths(JTable table, Insets insets,
boolean setMinimum,
boolean setMaximum) {
int columnCount = table.getColumnCount();
TableColumnModel tcm = table.getColumnModel();
int spare = (insets == null ? 0 : insets.left + insets.right);
for (int i = 0; i < columnCount; i++) {
int width = calculateColumnWidth(table, i);
width += spare;
TableColumn column = tcm.getColumn(i);
column.setPreferredWidth(width);
if (setMinimum == true) {
column.setMinWidth(width);
}
if (setMaximum == true) {
column.setMaxWidth(width);
}
}
}
// Sort an array of integers in place
public static void sort(int[] values) {
int length = values.length;
if (length > 1) {
for (int i = 0; i < length - 1 ; i++) {
for (int j = i + 1; j < length; j++) {
if (values[j] < values[i]) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
}
}
}
}
}
}
ToolTip Header Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1) */
import java.awt.BorderLayout;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
/**
* @version 1.0 02/25/99
*/
public class ToolTipHeaderTableExample extends JPanel {
public ToolTipHeaderTableExample() {
setLayout(new BorderLayout());
String[] headerStr = { "default", "jw", "ja", "la", "unknown" };
String[] toolTipStr = { "", "Javanese", "Japanese", "Latin" };
DefaultTableModel dm = new DefaultTableModel(headerStr, 4);
JTable table = new JTable(dm);
ToolTipHeader header = new ToolTipHeader(table.getColumnModel());
header.setToolTipStrings(toolTipStr);
header.setToolTipText("Default ToolTip TEXT");
table.setTableHeader(header);
JScrollPane pane = new JScrollPane(table);
add(pane, BorderLayout.CENTER);
}
public static void main(String[] args) {
JFrame f = new JFrame("ToolTipHeaderTable Example");
f.getContentPane().add(new ToolTipHeaderTableExample(),
BorderLayout.CENTER);
f.setSize(400, 100);
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
class ToolTipHeader extends JTableHeader {
String[] toolTips;
public ToolTipHeader(TableColumnModel model) {
super(model);
}
public String getToolTipText(MouseEvent e) {
int col = columnAtPoint(e.getPoint());
int modelCol = getTable().convertColumnIndexToModel(col);
String retStr;
try {
retStr = toolTips[modelCol];
} catch (NullPointerException ex) {
retStr = "";
} catch (ArrayIndexOutOfBoundsException ex) {
retStr = "";
}
if (retStr.length() < 1) {
retStr = super.getToolTipText(e);
}
return retStr;
}
public void setToolTipStrings(String[] toolTips) {
this.toolTips = toolTips;
}
}
}
ToolTip Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Font;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.NumberFormat;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.ImageIcon;
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.SwingConstants;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class ToolTipTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Tool Tip Table");
JTable tbl = new JTable(new CurrencyTableModel());
tbl
.setDefaultRenderer(java.lang.Number.class,
new ToolTipFractionCellRenderer(10, 3, 6,
SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tcm.getColumn(1).setPreferredWidth(100);
tcm.getColumn(1).setMinWidth(100);
// Add the stripe renderer.
StripedTableCellRenderer.installInTable(tbl, Color.lightGray,
Color.white, null, null);
// Add the custom header renderer
MultiLineHeaderRenderer headerRenderer = new MultiLineHeaderRenderer(
SwingConstants.CENTER, SwingConstants.BOTTOM);
headerRenderer.setBackground(Color.blue);
headerRenderer.setForeground(Color.white);
headerRenderer.setFont(new Font("Dialog", Font.BOLD, 12));
int columns = tableHeaders.length;
for (int i = 0; i < columns; i++) {
tcm.getColumn(i).setHeaderRenderer(headerRenderer);
tcm.getColumn(i).setHeaderValue(tableHeaders[i]);
}
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
// Header values. Note the table model provides
// string column names that are the default header
// values.
public static Object[][] tableHeaders = new Object[][] {
new String[] { "Currency" },
new String[] { "Yesterday"s", "Rate" },
new String[] { "Today"s", "Rate" },
new String[] { "Rate", "Change" } };
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class MultiLineHeaderRenderer extends JPanel implements TableCellRenderer {
public MultiLineHeaderRenderer(int horizontalAlignment,
int verticalAlignment) {
this.horizontalAlignment = horizontalAlignment;
this.verticalAlignment = verticalAlignment;
switch (horizontalAlignment) {
case SwingConstants.LEFT:
alignmentX = (float) 0.0;
break;
case SwingConstants.CENTER:
alignmentX = (float) 0.5;
break;
case SwingConstants.RIGHT:
alignmentX = (float) 1.0;
break;
default:
throw new IllegalArgumentException(
"Illegal horizontal alignment value");
}
setBorder(headerBorder);
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
setOpaque(true);
background = null;
}
public void setForeground(Color foreground) {
this.foreground = foreground;
super.setForeground(foreground);
}
public void setBackground(Color background) {
this.background = background;
super.setBackground(background);
}
public void setFont(Font font) {
this.font = font;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
removeAll();
invalidate();
if (value == null) {
// Do nothing if no value
return this;
}
// Set the foreground and background colors
// from the table header if they are not set
if (table != null) {
JTableHeader header = table.getTableHeader();
if (header != null) {
if (foreground == null) {
super.setForeground(header.getForeground());
}
if (background == null) {
super.setBackground(header.getBackground());
}
}
}
if (verticalAlignment != SwingConstants.TOP) {
add(Box.createVerticalGlue());
}
Object[] values;
int length;
if (value instanceof Object[]) {
// Input is an array - use it
values = (Object[]) value;
} else {
// Not an array - turn it into one
values = new Object[1];
values[0] = value;
}
length = values.length;
// Configure each row of the header using
// a separate JLabel. If a given row is
// a JComponent, add it directly..
for (int i = 0; i < length; i++) {
Object thisRow = values[i];
if (thisRow instanceof JComponent) {
add((JComponent) thisRow);
} else {
JLabel l = new JLabel();
setValue(l, thisRow, i);
add(l);
}
}
if (verticalAlignment != SwingConstants.BOTTOM) {
add(Box.createVerticalGlue());
}
return this;
}
// Configures a label for one line of the header.
// This can be overridden by derived classes
protected void setValue(JLabel l, Object value, int lineNumber) {
if (value != null && value instanceof Icon) {
l.setIcon((Icon) value);
} else {
l.setText(value == null ? "" : value.toString());
}
l.setHorizontalAlignment(horizontalAlignment);
l.setAlignmentX(alignmentX);
l.setOpaque(false);
l.setForeground(foreground);
l.setFont(font);
}
protected int verticalAlignment;
protected int horizontalAlignment;
protected float alignmentX;
// These attributes may be explicitly set
// They are defaulted to the colors and attributes
// of the table header
protected Color foreground;
protected Color background;
// These attributes have fixed defaults
protected Border headerBorder = UIManager
.getBorder("TableHeader.cellBorder");
protected Font font = UIManager.getFont("TableHeader.font");
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class ToolTipFractionCellRenderer extends FractionCellRenderer {
public ToolTipFractionCellRenderer(int integer, int fraction,
int maxFraction, int align) {
super(integer, fraction, align);
this.maxFraction = maxFraction; // Number of tooltip fraction digits
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Component comp = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(maxFraction);
formatter.setMinimumFractionDigits(maxFraction);
((JComponent) comp).setToolTipText(formatter
.format(((Number) value).doubleValue()));
}
return comp;
}
protected int maxFraction;
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
Total(Calculate) Row Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/*
* (swing1.1beta3) swing#960
*/
import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Vector;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
/**
* @version 1.0 12/03/98
*/
class DecimalRenderer extends DefaultTableCellRenderer {
DecimalFormat formatter;
DecimalRenderer(String pattern) {
this(new DecimalFormat(pattern));
}
DecimalRenderer(DecimalFormat formatter) {
this.formatter = formatter;
setHorizontalAlignment(JLabel.RIGHT);
}
public void setValue(Object value) {
setText((value == null) ? "" : formatter.format(((Double) value)
.doubleValue()));
}
}
public class TotalRowExample extends JFrame {
final private int TOTAL_ROW = 3;
final private int TOTAL_COLUMN = 1;
TotalRowExample() {
super("Total Row Example");
final DecimalFormat formatter = new DecimalFormat("###,##0.00");
DefaultTableModel dm = new DefaultTableModel() {
public void setValueAt(Object value, int row, int col) {
Vector rowVector = (Vector) dataVector.elementAt(row);
if (col == TOTAL_COLUMN) {
Double d = null;
if (value instanceof Double) {
d = (Double) value;
} else {
try {
d = new Double(((Number) formatter
.parse((String) value)).doubleValue());
} catch (ParseException ex) {
d = new Double(0.0);
}
}
rowVector.setElementAt(d, col);
} else {
rowVector.setElementAt(value, col);
}
}
public boolean isCellEditable(int row, int col) {
if (row == TOTAL_ROW)
return false;
return true;
}
public Class getColumnClass(int col) {
if (col == TOTAL_COLUMN)
return Number.class;
return String.class;
}
};
dm.setDataVector(new Object[][] { { "coffee", new Double(0.0) },
{ "tea", new Double(0.0) }, { "cocoa", new Double(0.0) },
{ "total", new Double(0.0) } },
new Object[] { "Item", "Price" });
JTable table = new JTable(dm) {
public void editingStopped(ChangeEvent e) {
super.editingStopped(e);
reCalcurate(getModel());
repaint();
}
};
table.getColumn("Price")
.setCellRenderer(new DecimalRenderer(formatter));
JScrollPane scroll = new JScrollPane(table);
Container content = getContentPane();
content.add(scroll);
setSize(300, 120);
setVisible(true);
}
private void reCalcurate(TableModel ml) {
if (ml == null)
return;
double total = 0.0;
for (int i = 0; i < TOTAL_ROW; i++) {
total += ((Double) ml.getValueAt(i, TOTAL_COLUMN)).doubleValue();
}
ml.setValueAt(new Double(total), TOTAL_ROW, TOTAL_COLUMN);
}
public static void main(String[] args) {
TotalRowExample frame = new TotalRowExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
Union Data Table Example
// Example from http://www.crionics.ru/products/opensource/faq/swing_ex/SwingExamples.html
/* (swing1.1beta3) */
import java.awt.Container;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Vector;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.SwingConstants;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
/**
* @version 1.0 11/09/98
*/
public class UnionDataExample extends JFrame {
UnionDataExample() {
super("UnionData Example");
setSize(300, 200);
final String[] headers = { "a", "b", "c", "d" };
final String[][] data = new String[6][headers.length];
final AbstractTableModel dmAB = new AbstractTableModel() {
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return headers.length;
}
public String getColumnName(int col) {
return headers[col];
}
public Object getValueAt(int row, int col) {
return data[row][col];
}
};
final int rowCountA = 3;
DefaultTableModel dmA = new DefaultTableModel(data, headers) {
public int getRowCount() {
return rowCountA;
}
public Object getValueAt(int row, int col) {
Vector rowVector = (Vector) dataVector.elementAt(row);
return rowVector.elementAt(col);
}
public void setValueAt(Object value, int row, int col) {
data[row][col] = (String) value;
Vector rowVector = (Vector) dataVector.elementAt(row);
rowVector.setElementAt(value, col);
TableModelEvent event = new TableModelEvent(this, row, row, col);
fireTableChanged(event);
dmAB.fireTableChanged(event);
}
};
DefaultTableModel dmB = new DefaultTableModel(data, headers) {
public int getRowCount() {
return rowCountA;
}
//public int getRowCount() { return data.length - rowCountA; }
public Object getValueAt(int row, int col) {
// Vector rowVector = (Vector) dataVector.elementAt(row
// + rowCountA);
Vector rowVector = (Vector) dataVector.elementAt(2);
return rowVector.elementAt(col);
}
public void setValueAt(Object value, int row, int col) {
int sRow = row + rowCountA;
data[sRow][col] = (String) value;
Vector rowVector = (Vector) dataVector.elementAt(sRow);
rowVector.setElementAt(value, col);
TableModelEvent event = new TableModelEvent(this, sRow, sRow,
col);
fireTableChanged(event);
dmAB.fireTableChanged(event);
}
};
JScrollPane scrollA = new JScrollPane(new JTable(dmA));
JScrollPane scrollB = new JScrollPane(new JTable(dmB));
JScrollPane scrollAB = new JScrollPane(new JTable(dmAB));
Box box = new Box(BoxLayout.Y_AXIS);
box.add(new JLabel("Table A"));
box.add(scrollA);
box.add(new JSeparator(SwingConstants.VERTICAL));
box.add(new JLabel("Table B"));
box.add(scrollB);
Box boxAB = new Box(BoxLayout.Y_AXIS);
boxAB.add(new JLabel("Table A + B"));
boxAB.add(scrollAB);
Container content = getContentPane();
content.setLayout(new BoxLayout(content, BoxLayout.X_AXIS));
content.add(box);
content.add(new JSeparator(SwingConstants.HORIZONTAL));
content.add(boxAB);
}
public static void main(String[] args) {
UnionDataExample frame = new UnionDataExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.setVisible(true);
}
}
Updatable Highlight Currency Table
/*
Core SWING Advanced Programming
By Kim Topley
ISBN: 0 13 083292 8
Publisher: Prentice Hall
*/
import java.awt.Color;
import java.awt.ruponent;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;
import java.util.EventObject;
import javax.swing.CellEditor;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.EventListenerList;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class UpdatableHighlightCurrencyTable {
public static void main(String[] args) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception evt) {}
JFrame f = new JFrame("Updatable Highlighted Currency Table");
JTable tbl = new JTable(new TestUpdatableCurrencyTableModel());
tbl.setDefaultRenderer(java.lang.Number.class,
new FractionCellRenderer(10, 3, SwingConstants.RIGHT));
TableColumnModel tcm = tbl.getColumnModel();
tcm.getColumn(0).setPreferredWidth(150);
tcm.getColumn(0).setMinWidth(150);
TextWithIconCellRenderer renderer = new TextWithIconCellRenderer();
tcm.getColumn(0).setCellRenderer(renderer);
tbl.setShowHorizontalLines(false);
tbl.setIntercellSpacing(new Dimension(1, 0));
// Add the stripe renderer in the leftmost four columns.
StripedTableCellRenderer.installInColumn(tbl, 0, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 1, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 2, Color.lightGray,
Color.white, null, null);
StripedTableCellRenderer.installInColumn(tbl, 3, Color.lightGray,
Color.white, null, null);
// Add the highlight renderer to the difference column.
// The following comparator makes it highlight
// cells with negative numeric values.
Comparator cmp = new Comparator() {
public boolean shouldHighlight(JTable tbl, Object value, int row,
int column) {
if (value instanceof Number) {
double columnValue = ((Number) value).doubleValue();
return columnValue < (double) 0.0;
}
return false;
}
};
tcm.getColumn(3).setCellRenderer(
new HighlightRenderer(cmp, null, Color.pink, Color.black,
Color.pink.darker(), Color.white));
// Install a button renderer in the last column
ButtonRenderer buttonRenderer = new ButtonRenderer();
buttonRenderer.setForeground(Color.blue);
buttonRenderer.setBackground(Color.lightGray);
tcm.getColumn(4).setCellRenderer(buttonRenderer);
// Install a button editor in the last column
TableCellEditor editor = new ButtonEditor(new JButton());
tcm.getColumn(4).setCellEditor(editor);
// Make the rows wide enough to take the buttons
tbl.setRowHeight(20);
tbl.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
tbl.setPreferredScrollableViewportSize(tbl.getPreferredSize());
JScrollPane sp = new JScrollPane(tbl);
f.getContentPane().add(sp, "Center");
f.pack();
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
});
f.setVisible(true);
}
}
class TestUpdatableCurrencyTableModel extends UpdatableCurrencyTableModel {
public void updateTable(Object value, int row, int column) {
System.out.println("Update for row " + row + " required.");
System.out.println("Values are " + getValueAt(row, 1) + ", "
+ getValueAt(row, 2) + "; diff is " + getValueAt(row, 3));
}
}
class FractionCellRenderer extends DefaultTableCellRenderer {
public FractionCellRenderer(int integer, int fraction, int align) {
this.integer = integer; // maximum integer digits
this.fraction = fraction; // exact number of fraction digits
this.align = align; // alignment (LEFT, CENTER, RIGHT)
}
protected void setValue(Object value) {
if (value != null && value instanceof Number) {
formatter.setMaximumIntegerDigits(integer);
formatter.setMaximumFractionDigits(fraction);
formatter.setMinimumFractionDigits(fraction);
setText(formatter.format(((Number) value).doubleValue()));
} else {
super.setValue(value);
}
setHorizontalAlignment(align);
}
protected int integer;
protected int fraction;
protected int align;
protected static NumberFormat formatter = NumberFormat.getInstance();
}
class TextWithIconCellRenderer extends DefaultTableCellRenderer {
protected void setValue(Object value) {
if (value instanceof DataWithIcon) {
if (value != null) {
DataWithIcon d = (DataWithIcon) value;
Object dataValue = d.getData();
setText(dataValue == null ? "" : dataValue.toString());
setIcon(d.getIcon());
setHorizontalTextPosition(SwingConstants.RIGHT);
setVerticalTextPosition(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
setVerticalAlignment(SwingConstants.CENTER);
} else {
setText("");
setIcon(null);
}
} else {
super.setValue(value);
}
}
}
class DataWithIcon {
public DataWithIcon(Object data, Icon icon) {
this.data = data;
this.icon = icon;
}
public Icon getIcon() {
return icon;
}
public Object getData() {
return data;
}
public String toString() {
return data.toString();
}
protected Icon icon;
protected Object data;
}
class StripedTableCellRenderer implements TableCellRenderer {
public StripedTableCellRenderer(TableCellRenderer targetRenderer,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
this.targetRenderer = targetRenderer;
this.evenBack = evenBack;
this.evenFore = evenFore;
this.oddBack = oddBack;
this.oddFore = oddFore;
}
// Implementation of TableCellRenderer interface
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
// Get default renderer from the table
renderer = table.getDefaultRenderer(table.getColumnClass(column));
}
// Let the real renderer create the component
Component comp = renderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
// Now apply the stripe effect
if (isSelected == false && hasFocus == false) {
if ((row & 1) == 0) {
comp.setBackground(evenBack != null ? evenBack : table
.getBackground());
comp.setForeground(evenFore != null ? evenFore : table
.getForeground());
} else {
comp.setBackground(oddBack != null ? oddBack : table
.getBackground());
comp.setForeground(oddFore != null ? oddFore : table
.getForeground());
}
}
return comp;
}
// Convenience method to apply this renderer to single column
public static void installInColumn(JTable table, int columnIndex,
Color evenBack, Color evenFore, Color oddBack, Color oddFore) {
TableColumn tc = table.getColumnModel().getColumn(columnIndex);
// Get the cell renderer for this column, if any
TableCellRenderer targetRenderer = tc.getCellRenderer();
// Create a new StripedTableCellRenderer and install it
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
}
// Convenience method to apply this renderer to an entire table
public static void installInTable(JTable table, Color evenBack,
Color evenFore, Color oddBack, Color oddFore) {
StripedTableCellRenderer sharedInstance = null;
int columns = table.getColumnCount();
for (int i = 0; i < columns; i++) {
TableColumn tc = table.getColumnModel().getColumn(i);
TableCellRenderer targetRenderer = tc.getCellRenderer();
if (targetRenderer != null) {
// This column has a specific renderer
tc.setCellRenderer(new StripedTableCellRenderer(targetRenderer,
evenBack, evenFore, oddBack, oddFore));
} else {
// This column uses a class renderer - use a shared renderer
if (sharedInstance == null) {
sharedInstance = new StripedTableCellRenderer(null,
evenBack, evenFore, oddBack, oddFore);
}
tc.setCellRenderer(sharedInstance);
}
}
}
protected TableCellRenderer targetRenderer;
protected Color evenBack;
protected Color evenFore;
protected Color oddBack;
protected Color oddFore;
}
class HighlightRenderer implements TableCellRenderer {
public HighlightRenderer(Comparator cmp, TableCellRenderer targetRenderer,
Color backColor, Color foreColor, Color highlightBack,
Color highlightFore) {
this.cmp = cmp;
this.targetRenderer = targetRenderer;
this.backColor = backColor;
this.foreColor = foreColor;
this.highlightBack = highlightBack;
this.highlightFore = highlightFore;
}
public Component getTableCellRendererComponent(JTable tbl, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
TableCellRenderer renderer = targetRenderer;
if (renderer == null) {
renderer = tbl.getDefaultRenderer(tbl.getColumnClass(column));
}
Component comp = renderer.getTableCellRendererComponent(tbl, value,
isSelected, hasFocus, row, column);
if (isSelected == false && hasFocus == false && value != null) {
if (cmp.shouldHighlight(tbl, value, row, column)) {
comp.setForeground(highlightFore);
comp.setBackground(highlightBack);
} else {
comp.setForeground(foreColor);
comp.setBackground(backColor);
}
}
return comp;
}
protected Comparator cmp;
protected TableCellRenderer targetRenderer;
protected Color backColor;
protected Color foreColor;
protected Color highlightBack;
protected Color highlightFore;
}
interface Comparator {
public abstract boolean shouldHighlight(JTable tbl, Object value, int row,
int column);
}
abstract class UpdatableCurrencyTableModel extends EditableCurrencyTableModel {
public int getColumnCount() {
return super.getColumnCount() + 1;
}
public Object getValueAt(int row, int column) {
if (column == BUTTON_COLUMN) {
return "Update";
}
return super.getValueAt(row, column);
}
public Class getColumnClass(int column) {
if (column == BUTTON_COLUMN) {
return String.class;
}
return super.getColumnClass(column);
}
public String getColumnName(int column) {
if (column == BUTTON_COLUMN) {
return "";
}
return super.getColumnName(column);
}
public boolean isCellEditable(int row, int column) {
return column == BUTTON_COLUMN || super.isCellEditable(row, column);
}
public void setValueAt(Object value, int row, int column) {
if (column == BUTTON_COLUMN) {
// Button press - do whatever is needed to update the table source
updateTable(value, row, column);
return;
}
// Other columns - use superclass
super.setValueAt(value, row, column);
}
// Used to implement the table update
protected abstract void updateTable(Object value, int row, int column);
protected static final int BUTTON_COLUMN = 4;
}
class BasicCellEditor implements CellEditor, PropertyChangeListener {
public BasicCellEditor() {
this.editor = null;
}
public BasicCellEditor(JComponent editor) {
this.editor = editor;
editor.addPropertyChangeListener(this);
}
public Object getCellEditorValue() {
return null;
}
public boolean isCellEditable(EventObject evt) {
editingEvent = evt;
return true;
}
public boolean shouldSelectCell(EventObject evt) {
return true;
}
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
public void cancelCellEditing() {
fireEditingCanceled();
}
public void addCellEditorListener(CellEditorListener l) {
listeners.add(CellEditorListener.class, l);
}
public void removeCellEditorListener(CellEditorListener l) {
listeners.remove(CellEditorListener.class, l);
}
// Returns the editing component
public JComponent getComponent() {
return editor;
}
// Sets the editing component
public void setComponent(JComponent comp) {
editor = comp;
}
// Returns the event that triggered the edit
public EventObject getEditingEvent() {
return editingEvent;
}
// Method invoked when the editor is installed in the table.
// Overridden in derived classes to take any convenient
// action.
public void editingStarted(EventObject event) {
}
protected void fireEditingStopped() {
Object[] l = listeners.getListenerList();
for (int i = l.length - 2; i >= 0; i -= 2) {
if (l[i] == CellEditorListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((CellEditorListener) l[i + 1]).editingStopped(changeEvent);
}
}
}
protected void fireEditingCanceled() {
Object[] l = listeners.getListenerList();
for (int i = l.length - 2; i >= 0; i -= 2) {
if (l[i] == CellEditorListener.class) {
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((CellEditorListener) l[i + 1]).editingCanceled(changeEvent);
}
}
}
// Implementation of the PropertyChangeListener interface
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("ancestor")
&& evt.getNewValue() != null) {
// Added to table - notify the editor
editingStarted(editingEvent);
}
}
protected static JCheckBox checkBox = new JCheckBox();
protected static ChangeEvent changeEvent;
protected JComponent editor;
protected EventListenerList listeners = new EventListenerList();
protected EventObject editingEvent;
}
class ButtonEditor extends BasicCellEditor implements ActionListener,
TableCellEditor {
public ButtonEditor(JButton button) {
super(button);
button.addActionListener(this);
}
public void setForeground(Color foreground) {
this.foreground = foreground;
editor.setForeground(foreground);
}
public void setBackground(Color background) {
this.background = background;
editor.setBackground(background);
}
public void setFont(Font font) {
this.font = font;
editor.setFont(font);
}
public Object getCellEditorValue() {
return value;
}
public void editingStarted(EventObject event) {
// Edit starting - click the button if necessary
if (!(event instanceof MouseEvent)) {
// Keyboard event - click the button
SwingUtilities.invokeLater(new Runnable() {
public void run() {
((JButton) editor).doClick();
}
});
}
}
public Component getTableCellEditorComponent(JTable tbl, Object value,
boolean isSelected, int row, int column) {
editor.setForeground(foreground != null ? foreground : tbl
.getForeground());
editor.setBackground(background != null ? background : tbl
.getBackground());
editor.setFont(font != null ? font : tbl.getFont());
this.value = value;
setValue(value);
return editor;
}
protected void setValue(Object value) {
JButton button = (JButton) editor;
if (value == null) {
button.setText("");
button.setIcon(null);
} else if (value instanceof Icon) {
button.setText("");
button.setIcon((Icon) value);
} else if (value instanceof DataWithIcon) {
DataWithIcon d = (DataWithIcon) value;
button.setText(d.toString());
button.setIcon(d.getIcon());
} else {
button.setText(value.toString());
button.setIcon(null);
}
}
public void actionPerformed(ActionEvent evt) {
// Button pressed - stop the edit
stopCellEditing();
}
protected Object value;
protected Color foreground;
protected Color background;
protected Font font;
}
class EditableCurrencyTableModel extends CurrencyTableModel {
public boolean isCellEditable(int row, int column) {
return column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN;
}
public void setValueAt(Object value, int row, int column) {
try {
if (column == OLD_RATE_COLUMN || column == NEW_RATE_COLUMN) {
Double newObjectValue; // New value as an Object
double newValue; // double, for validity checking
if (value instanceof Number) {
// Convert Number to Double
newValue = ((Number) value).doubleValue();
newObjectValue = new Double(newValue);
} else if (value instanceof String) {
// Convert a String to a Double
newObjectValue = new Double((String) value);
newValue = newObjectValue.doubleValue();
} else {
// Unrecognized - ignore
return;
}
if (newValue > (double) 0.0) {
// Store new value, but reject zero or negative values
data[row][column] = newObjectValue;
data[row][DIFF_COLUMN] = new Double(
((Double) data[row][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[row][OLD_RATE_COLUMN])
.doubleValue());
fireTableRowsUpdated(row, row);
}
}
} catch (NumberFormatException e) {
// Ignore a badly-formatted number
}
}
}
class CurrencyTableModel extends AbstractTableModel {
protected String[] columnNames = { "Currency", "Yesterday", "Today",
"Change" };
// Constructor: calculate currency change to create the last column
public CurrencyTableModel() {
for (int i = 0; i < data.length; i++) {
data[i][DIFF_COLUMN] = new Double(
((Double) data[i][NEW_RATE_COLUMN]).doubleValue()
- ((Double) data[i][OLD_RATE_COLUMN]).doubleValue());
}
}
// Implementation of TableModel interface
public int getRowCount() {
return data.length;
}
public int getColumnCount() {
return COLUMN_COUNT;
}
public Object getValueAt(int row, int column) {
return data[row][column];
}
public Class getColumnClass(int column) {
return (data[0][column]).getClass();
}
public String getColumnName(int column) {
return columnNames[column];
}
protected static final int OLD_RATE_COLUMN = 1;
protected static final int NEW_RATE_COLUMN = 2;
protected static final int DIFF_COLUMN = 3;
protected static final int COLUMN_COUNT = 4;
protected static final Class thisClass = CurrencyTableModel.class;
protected Object[][] data = new Object[][] {
{
new DataWithIcon("Belgian Franc", new ImageIcon(thisClass
.getResource("belgium.gif"))),
new Double(37.6460110), new Double(37.6508921), null },
{
new DataWithIcon("British Pound", new ImageIcon(thisClass
.getResource("gb.gif"))), new Double(0.6213051),
new Double(0.6104102), null },
{
new DataWithIcon("Canadian Dollar", new ImageIcon(thisClass
.getResource("canada.gif"))),
new Double(1.4651209), new Double(1.5011104), null },
{
new DataWithIcon("French Franc", new ImageIcon(thisClass
.getResource("france.gif"))),
new Double(6.1060001), new Double(6.0100101), null },
{
new DataWithIcon("Italian Lire", new ImageIcon(thisClass
.getResource("italy.gif"))),
new Double(1181.3668977), new Double(1182.104), null },
{
new DataWithIcon("German Mark", new ImageIcon(thisClass
.getResource("germany.gif"))),
new Double(1.8191804), new Double(1.8223421), null },
{
new DataWithIcon("Japanese Yen", new ImageIcon(thisClass
.getResource("japan.gif"))),
new Double(141.0815412), new Double(121.0040432), null } };
}
class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
this.border = getBorder();
this.setOpaque(true);
}
public void setForeground(Color foreground) {
this.foreground = foreground;
super.setForeground(foreground);
}
public void setBackground(Color background) {
this.background = background;
super.setBackground(background);
}
public void setFont(Font font) {
this.font = font;
super.setFont(font);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
Color cellForeground = foreground != null ? foreground : table
.getForeground();
Color cellBackground = background != null ? background : table
.getBackground();
setFont(font != null ? font : table.getFont());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
if (table.isCellEditable(row, column)) {
cellForeground = UIManager
.getColor("Table.focusCellForeground");
cellBackground = UIManager
.getColor("Table.focusCellBackground");
}
} else {
setBorder(border);
}
super.setForeground(cellForeground);
super.setBackground(cellBackground);
// Customize the component"s appearance
setValue(value);
return this;
}
protected void setValue(Object value) {
if (value == null) {
setText("");
setIcon(null);
} else if (value instanceof Icon) {
setText("");
setIcon((Icon) value);
} else if (value instanceof DataWithIcon) {
DataWithIcon d = (DataWithIcon) value;
setText(d.toString());
setIcon(d.getIcon());
} else {
setText(value.toString());
setIcon(null);
}
}
protected Color foreground;
protected Color background;
protected Font font;
protected Border border;
}