Expense Table
/*
Swing, Second Edition
by Matthew Robinson, Pavel Vorobiev
*/
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.text.SimpleDateFormat;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class ExpenseReport extends JFrame
{
protected JTable m_table;
protected ExpenseReportData m_data;
protected JLabel m_title;
public ExpenseReport() {
super("Expense Report");
setSize(570, 200);
m_data = new ExpenseReportData(this);
m_table = new JTable();
m_table.setAutoCreateColumnsFromModel(false);
m_table.setModel(m_data);
m_table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
for (int k = 0; k < ExpenseReportData.m_columns.length; k++) {
TableCellRenderer renderer;
if (k==ExpenseReportData.COL_APPROVED)
renderer = new CheckCellRenderer();
else {
DefaultTableCellRenderer textRenderer =
new DefaultTableCellRenderer();
textRenderer.setHorizontalAlignment(
ExpenseReportData.m_columns[k].m_alignment);
renderer = textRenderer;
}
TableCellEditor editor;
if (k==ExpenseReportData.COL_CATEGORY)
editor = new DefaultCellEditor(new JComboBox(
ExpenseReportData.CATEGORIES));
else if (k==ExpenseReportData.COL_APPROVED)
editor = new DefaultCellEditor(new JCheckBox());
else
editor = new DefaultCellEditor(new JTextField());
TableColumn column = new TableColumn(k,
ExpenseReportData.m_columns[k].m_width,
renderer, editor);
m_table.addColumn(column);
}
JTableHeader header = m_table.getTableHeader();
header.setUpdateTableInRealTime(false);
JScrollPane ps = new JScrollPane();
ps.setSize(550, 150);
ps.getViewport().add(m_table);
getContentPane().add(ps, BorderLayout.CENTER);
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
ImageIcon penny = new ImageIcon("penny.gif");
m_title = new JLabel("Total: $",
penny, JButton.LEFT);
m_title.setForeground(Color.black);
m_title.setAlignmentY(0.5f);
p.add(m_title);
p.add(Box.createHorizontalGlue());
JButton bt = new JButton("Insert before");
bt.setMnemonic('b');
bt.setAlignmentY(0.5f);
ActionListener lst = new ActionListener() {
public void actionPerformed(ActionEvent e) {
int row = m_table.getSelectedRow();
m_data.insert(row);
m_table.tableChanged(new TableModelEvent(
m_data, row, row, TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT));
m_table.repaint();
}
};
bt.addActionListener(lst);
p.add(bt);
bt = new JButton("Insert after");
bt.setMnemonic('a');
bt.setAlignmentY(0.5f);
lst = new ActionListener() {
public void actionPerformed(ActionEvent e) {
int row = m_table.getSelectedRow();
m_data.insert(row+1);
m_table.tableChanged(new TableModelEvent(
m_data, row+1, row+1, TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT));
m_table.repaint();
}
};
bt.addActionListener(lst);
p.add(bt);
bt = new JButton("Delete row");
bt.setMnemonic('d');
bt.setAlignmentY(0.5f);
lst = new ActionListener() {
public void actionPerformed(ActionEvent e) {
int row = m_table.getSelectedRow();
if (m_data.delete(row)) {
m_table.tableChanged(new TableModelEvent(
m_data, row, row, TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT));
m_table.repaint();
calcTotal();
}
}
};
bt.addActionListener(lst);
p.add(bt);
getContentPane().add(p, BorderLayout.SOUTH);
calcTotal();
WindowListener wndCloser = new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
};
addWindowListener(wndCloser);
setVisible(true);
}
public void calcTotal() {
double total = 0;
for (int k=0; k<m_data.getRowCount(); k++) {
Double amount = (Double)m_data.getValueAt(k,
ExpenseReportData.COL_AMOUNT);
total += amount.doubleValue();
}
m_title.setText("Total: $"+total);
}
public static void main(String argv[]) {
new ExpenseReport();
}
}
class CheckCellRenderer extends JCheckBox implements TableCellRenderer
{
protected static Border m_noFocusBorder;
public CheckCellRenderer() {
super();
m_noFocusBorder = new EmptyBorder(1, 2, 1, 2);
setOpaque(true);
setBorder(m_noFocusBorder);
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column)
{
if (value instanceof Boolean) {
Boolean b = (Boolean)value;
setSelected(b.booleanValue());
}
setBackground(isSelected && !hasFocus ?
table.getSelectionBackground() : table.getBackground());
setForeground(isSelected && !hasFocus ?
table.getSelectionForeground() : table.getForeground());
setFont(table.getFont());
setBorder(hasFocus ? UIManager.getBorder(
"Table.focusCellHighlightBorder") : m_noFocusBorder);
return this;
}
}
class ExpenseData
{
public Date m_date;
public Double m_amount;
public Integer m_category;
public Boolean m_approved;
public String m_description;
public ExpenseData() {
m_date = new Date();
m_amount = new Double(0);
m_category = new Integer(1);
m_approved = new Boolean(false);
m_description = "";
}
public ExpenseData(Date date, double amount, int category,
boolean approved, String description)
{
m_date = date;
m_amount = new Double(amount);
m_category = new Integer(category);
m_approved = new Boolean(approved);
m_description = description;
}
}
class ColumnData
{
public String m_title;
int m_width;
int m_alignment;
public ColumnData(String title, int width, int alignment) {
m_title = title;
m_width = width;
m_alignment = alignment;
}
}
class ExpenseReportData extends AbstractTableModel
{
public static final ColumnData m_columns[] = {
new ColumnData( "Date", 80, JLabel.LEFT ),
new ColumnData( "Amount", 80, JLabel.RIGHT ),
new ColumnData( "Category", 130, JLabel.LEFT ),
new ColumnData( "Approved", 80, JLabel.LEFT ),
new ColumnData( "Description", 180, JLabel.LEFT )
};
public static final int COL_DATE = 0;
public static final int COL_AMOUNT = 1;
public static final int COL_CATEGORY = 2;
public static final int COL_APPROVED = 3;
public static final int COL_DESCR = 4;
public static final String[] CATEGORIES = {
"Fares", "Logging", "Business meals", "Others"
};
protected ExpenseReport m_parent;
protected SimpleDateFormat m_frm;
protected Vector m_vector;
public ExpenseReportData(ExpenseReport parent) {
m_parent = parent;
m_frm = new SimpleDateFormat("MM/dd/yy");
m_vector = new Vector();
setDefaultData();
}
public void setDefaultData() {
m_vector.removeAllElements();
try {
m_vector.addElement(new ExpenseData(
m_frm.parse("04/06/99"), 200, 0, true,
"Airline tickets"));
m_vector.addElement(new ExpenseData(
m_frm.parse("04/06/99"), 50, 2, false,
"Lunch with client"));
m_vector.addElement(new ExpenseData(
m_frm.parse("04/06/99"), 120, 1, true,
"Hotel"));
}
catch (java.text.ParseException ex) {}
}
public int getRowCount() {
return m_vector==null ? 0 : m_vector.size();
}
public int getColumnCount() {
return m_columns.length;
}
public String getColumnName(int column) {
return m_columns[column].m_title;
}
public boolean isCellEditable(int nRow, int nCol) {
return true;
}
public Object getValueAt(int nRow, int nCol) {
if (nRow < 0 || nRow>=getRowCount())
return "";
ExpenseData row = (ExpenseData)m_vector.elementAt(nRow);
switch (nCol) {
case COL_DATE: return m_frm.format(row.m_date);
case COL_AMOUNT: return row.m_amount;
case COL_CATEGORY: return CATEGORIES[row.m_category.intValue()];
case COL_APPROVED: return row.m_approved;
case COL_DESCR: return row.m_description;
}
return "";
}
public void setValueAt(Object value, int nRow, int nCol) {
if (nRow < 0 || nRow>=getRowCount())
return;
ExpenseData row = (ExpenseData)m_vector.elementAt(nRow);
String svalue = value.toString();
switch (nCol) {
case COL_DATE:
Date date = null;
try {
date = m_frm.parse(svalue);
}
catch (java.text.ParseException ex) {
date = null;
}
if (date == null) {
JOptionPane.showMessageDialog(null,
svalue+" is not a valid date",
"Warning", JOptionPane.WARNING_MESSAGE);
return;
}
row.m_date = date;
break;
case COL_AMOUNT:
try {
row.m_amount = new Double(svalue);
}
catch (NumberFormatException e) { break; }
m_parent.calcTotal();
break;
case COL_CATEGORY:
for (int k=0; k<CATEGORIES.length; k++)
if (svalue.equals(CATEGORIES[k])) {
row.m_category = new Integer(k);
break;
}
break;
case COL_APPROVED:
row.m_approved = (Boolean)value;
break;
case COL_DESCR:
row.m_description = svalue;
break;
}
}
public void insert(int row) {
if (row < 0)
row = 0;
if (row > m_vector.size())
row = m_vector.size();
m_vector.insertElementAt(new ExpenseData(), row);
}
public boolean delete(int row) {
if (row < 0 || row >= m_vector.size())
return false;
m_vector.remove(row);
return true;
}
}
Related examples in the same category
1. | Creating a JTable Component | | |
2. | Creates tables that allow rows and columns to be added or deleted | | |
3. | Build a table from list data and column names | | |
4. | Getting the Number of Rows and Columns in a JTable Component | | |
5. | Appending a Row to a JTable Component | | |
6. | Add columns to a table through DefaultTableModel | | |
7. | Insert a row to a table through DefaultTableModel | | |
8. | Insert a row to a table through DefaultTableModel at specified row | | |
9. | Scroll Table Sample | | |
10. | Simple demonstration of JTable | | |
11. | Create a table with two dimensional array | | |
12. | Create table with Unicode data | | |
13. | Resize Table | | |
14. | StockTable 6: Action and Dynamic Display | | |
15. | JTable selection events | | |
16. | A table with the ability to play with row and column selections | | |
17. | Table Selection mode | | |
18. | Display ResultSet in Table (JTable) | | |
19. | JTable(Table) with JDBC and ResultSet | | |
20. | List UI Properties in a JTable and sortable | | |
21. | Property Table: Use JTable to display and edit properties | | |
22. | Table with tool tips for both cells and column headers | | |
23. | StockTable 4: Table Sorter | | |
24. | JTable sorter:click the table header to sort a column and a table | | |
25. | Creating image out of a JTable | | |
26. | JTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); | | |
27. | JTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | | |
28. | JTable.setColumnSelectionAllowed(boolean b); | | |
29. | JTable.setRowSelectionAllowed(boolean b); | | |
30. | JTable.setCellSelectionEnabled(boolean b); | | |
31. | Handle selection and model change events for a JTable. | | |
32. | ListSelectionModel rowSelMod = JTable.getSelectionModel(); | | |
33. | ListSelectionModel colSelMod = JTable.getColumnModel().getSelectionModel(); | | |
34. | JTree.getModel().addTreeModelListener(new TreeModelListener()) | | |
35. | Move the last visible column so it becomes the first visible column | | |
36. | the last column is moved to the first position | | |
37. | Allowing the User to Resize a Column in a JTable Component | | |
38. | Retrieve the value in the visible cell (1,2) in a JTable | | |
39. | Retrieve the value in cell (1,2) from the model | | |
40. | Change a cell in the 2nd visible column | | |
41. | Change a cell in the 3rd column in the model | | |
42. | Showing the Table Header in a Non-Scrollable JTable Component | | |
43. | Changing the Name of a Column in a JTable Component | | |
44. | Displaying an Icon in a Column Head of a JTable Component | | |
45. | Implementing Variable-Height Column Headers in a JTable Component | | |
46. | Removing the Column Headers from a Scrollable in a JTable Component | | |
47. | Creating a Custom Column Header Renderer in a JTable Component | | |
48. | Setting Column Header Tool Tips in a JTable Components | | |
49. | Setting Tool Tips on Cells in a JTable Component | | |
50. | Enable row selection (default) in a JTable | | |
51. | Enable column selection in a JTable | | |
52. | Enable cell selection in a JTable | | |
53. | Get default selection mode:MULTIPLE_INTERVAL_SELECTION | | |
54. | Allow only single a selection | | |
55. | Allow selection to span one contiguous set of rows, visible columns, or block of cells | | |
56. | Allow multiple selections of rows, visible columns, or cell blocks (default) | | |
57. | Select a column - column 0 in a JTable | | |
58. | Select an additional range of columns - columns 1 to 2 | | |
59. | Deselect a range of columns - columns 0 to 1 | | |
60. | Select a row - row 0 | | |
61. | Select an additional range of rows - rows 1 to 2 | | |
62. | Deselect a range of rows - rows 0 to 1 | | |
63. | Select a cell: cell (2,1) | | |
64. | Extend the selection to include all cells (5,3) | | |
65. | Deselect a cell: cell (3,2), All cells in the row and column containing (3,2) are deselected. | | |
66. | Toggles the selection state, if it were called again, it exactly reverses the first call. | | |
67. | Select all cells | | |
68. | Deselect all cells | | |
69. | Column selection is enabled, get the indices of the selected columns | | |
70. | Row selection is enabled, Get the indices of the selected rows | | |
71. | Get selected row and selected index | | |
72. | Get the min and max ranges of selected cells | | |
73. | Check each cell in the min and max ranges of selected cells | | |
74. | Disabling Selections in a JTable Component | | |
75. | Getting the Anchor Cell in a JTable Component | | |
76. | Creating a Scrollable JTable Component | | |
77. | Disable auto resizing to make the table horizontal scrollable | | |
78. | Determining If a Cell Is Visible in a JTable Component | | |
79. | Making a Cell Visible in a JTable Component | | |
80. | Scrolling a Cell to the Center of a JTable Component | | |
81. | Show both horizontal and vertical grid lines (the default) | | |
82. | Don't show any grid lines | | |
83. | Show only vertical grid lines | | |
84. | Show only horizontal grid lines | | |
85. | Set the grid color | | |
86. | Getting the Gap Size Between Cells in a JTable Component | | |
87. | Add 5 spaces to the left and right sides of a cell. | | |
88. | Increase the row height | | |
89. | Programmatically Starting Cell Editing in a JTable Component | | |
90. | Save the current value in the cell being edited and stops the editing process | | |
91. | Discard any changes made by the user and stops the editing process | | |
92. | Disabling User Edits in a JTable | | |
93. | Disabling User Edits in a JTable with DefaultTableModel | | |
94. | Sorting the Rows in a JTable Component Based on a Column | | |
95. | Sorting a Column in a JTable Component | | |
96. | Listening for Selection Events in a JTable Component | | |
97. | Listening for Changes to the Rows and Columns of a JTable Component | | |
98. | Listening for Column-Related Changes in a JTable Component | | |
99. | Listening for Clicks on a Column Header in a JTable Component | | |
100. | Sorting and Filtering Tables | | |
101. | Use a regexFilter to filter table content | | |
102. | Creating a JTable with rows of variable height | | |
103. | Scroll JTable To Center | | |