I am not sure why the editor i am setting for my jtable is not being called. I used the editor example from another SO Question.
When i edit my jtable it simply edits as string... i expected it to accept only number values. may be some exception if i type any other text... but i dont think the editor is being called here when i edit my table.
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.NumberFormatter;
import java.awt.*;
import java.awt.event.*;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;
public class Grow extends JFrame {
private static final Object[][] rowData = {{"Hello", "World"}};
private static final Object[] columnNames = {"A", "B"};
private JTable table;
private DefaultTableModel model;
public Grow() {
Container c = getContentPane();
c.setLayout(new BorderLayout());
model = new DefaultTableModel(rowData, columnNames);
table = new JTable();
table.setModel(model);
c.add(new JScrollPane(table), BorderLayout.CENTER);
JButton add = new JButton("Add");
JButton delete = new JButton("Delete");
c.add(add, BorderLayout.LINE_START);
add.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
model.addRow(rowData[0]);
}
});
table.setCellEditor(new NumberCellEditor());
c.add(delete, BorderLayout.LINE_END);
delete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
if(table.getSelectedRow()>-1)
model.removeRow(table.getSelectedRow());
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
}
class NumberCellEditor extends DefaultCellEditor {
/**
*
*/
private static final long serialVersionUID = 1L;
public NumberCellEditor(){
super(new JFormattedTextField());
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JFormattedTextField editor = (JFormattedTextField) super.getTableCellEditorComponent(table, value, isSelected, row, column);
if (value!=null){
DecimalFormat numberFormat = new DecimalFormat("#,##0.00;(#,##0.00)");
editor.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(numberFormat)));
Number num = (Number) value;
String text = numberFormat.format(num);
editor.setHorizontalAlignment(SwingConstants.RIGHT);
editor.setText(text);
}
System.out.println(value);
return editor;
}
/*@Override
public boolean stopCellEditing() {
try {
// try to get the value
//this.getCellEditorValue();
return super.stopCellEditing();
} catch (Exception ex) {
return false;
}
}
*/
@Override
public Object getCellEditorValue() {
// get content of textField
String str = (String) super.getCellEditorValue();
if (str == null) {
return null;
}
if (str.length() == 0) {
return null;
}
// try to parse a number
try {
ParsePosition pos = new ParsePosition(0);
Number n = NumberFormat.getInstance().parse(str, pos);
if (pos.getIndex() != str.length()) {
throw new ParseException(
"parsing incomplete", pos.getIndex());
}
// return an instance of column class
return new Float(n.floatValue());
} catch (ParseException pex) {
throw new RuntimeException(pex);
}
}
}
public static void main(String[] args) {
Grow g = new Grow();
g.setLocationRelativeTo(null);
g.setVisible(true);
}
}
use plain vanilla JTextField
with DocumentFilter
instead of JFormattedTextField
as editors Component
.
I cant comment something, attached start_point for JFormattedTextField
with XxxFormat
(important details are in offical Oracle tutorial, APIs How to use FormattedTextField
, NumberFormat
etc.)
you can to add InternationalFormatter for filtering only Numbers
e.g.
InternationalFormatter formatter = new InternationalFormatter(format);
formatter.setAllowsInvalid(false);
//formatter.setMinimum(0.0);
//formatter.setMaximum(1000.00);
screen_shot
from code
import java.awt.Component;
import java.awt.EventQueue;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
public class EditorAsRendererTableTest {
public EditorAsRendererTableTest() {
JTable table = new JTable(3, 2);
TableColumnModel colModel = table.getColumnModel();
colModel.getColumn(0).setCellEditor(new MyCellEditor());
colModel.getColumn(0).setCellRenderer(new MyCellEditor());
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new EditorAsRendererTableTest();
}
});
}
private class MyCellEditor extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private static final long serialVersionUID = 1L;
private JFormattedTextField renderer;
private JFormattedTextField editor;
private NumberFormat format = DecimalFormat.getInstance();
public MyCellEditor() {
format.setMinimumFractionDigits(2);
format.setMaximumFractionDigits(4);
format.setRoundingMode(RoundingMode.HALF_UP);
renderer = new JFormattedTextField(format);
renderer.setBorder(null);
editor = new JFormattedTextField(format);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
renderer.setValue(value);
return renderer;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
editor.setValue(value);
return editor;
}
@Override
public boolean stopCellEditing() {
try {
editor.commitEdit();
} catch (ParseException e) {
return false;
}
return super.stopCellEditing();
}
@Override
public Object getCellEditorValue() {
return editor.getValue();
}
}
}