使用JTable单元格编辑器

时间:2013-10-31 13:31:46

标签: java swing jtable number-formatting tablecelleditor

我不确定为什么我为jtable设置的编辑器没有被调用。我使用了另一个SO Question的编辑器示例。

当我编辑我的jtable时,它只是编辑为字符串...我希望它只接受数字值。如果我输入任何其他文本可能会有一些例外...但我不认为编辑我的表时会在这里调用编辑器。

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

2 个答案:

答案 0 :(得分:2)

  • 使用普通香草JTextFieldDocumentFilter代替JFormattedTextField作为编辑Component

  • 我无法评论某些内容,为JFormattedTextField添加XxxFormat的start_point(重要的详细信息在官方Oracle教程,API How to use FormattedTextFieldNumberFormat等。)< / p>

  • 您可以添加InternationalFormatter以仅过滤Numbers

e.g。

InternationalFormatter formatter = new InternationalFormatter(format);
formatter.setAllowsInvalid(false);
//formatter.setMinimum(0.0);
//formatter.setMaximum(1000.00);

screen_shot

enter image description here

来自代码

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();
        }
    }
}

答案 1 :(得分:2)

  

我希望它只接受数字值

通常,无需创建自定义编辑器。只需覆盖TableModel的getColumnClass()方法,即可返回存储在模型中的正确数据类,该表将使用适当的渲染器和编辑器。

但是,如果您希望编辑器限制小数位或对数字进行范围检查,那么您可以使用自定义编辑器。