Hi,

Please find the code for a JTable that shows an expense report. The program
works fine, however, editing data gives me a problem. When you try to edit
text, you will see that the input is being adited to the existing value.
Anyone knows how to ensure that you put the value directly into the cell?


package test;

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);
b