【问题标题】:Simple Edittable JTable With Input Validation带有输入验证的简单可编辑 JTable
【发布时间】:2015-01-27 13:34:46
【问题描述】:

我想写一个非常简单的JTable。

用户可以通过输入有效的双精度来编辑单元格。如果用户的输入无效(即他们输入了一个字符串),我希望我的表格丢弃无效输入,显示最后一个正确的输入,并向用户显示错误消息。

我还希望表格中的数字格式如下: “###.##%”

我该怎么做?

其他信息
我知道我需要做的一些点点滴滴,但在连接这些点时遇到了麻烦。

例如,我知道要获得正确的格式,我必须将DefaultTableCellRenderer 子类化,但是我不确定getTableCellRendererComponent() 方法中究竟需要什么。

我很确定我必须继承 DefaultCellEditor 才能使编辑和错误检查正常工作。不过,我已经阅读了很多关于此的不同内容。我不确定检查有效输入的最佳位置在哪里。我也读过InputVerifier 并且不知道如何使用它或者我什至应该使用它。

这样的事情如何工作的一个小例子以及我必须扩展/覆盖的不同类/方法的简要说明对我很有帮助。

谢谢

【问题讨论】:

    标签: java swing validation jtable tablecelleditor


    【解决方案1】:

    我知道要获得正确的格式,我必须将 DefaultTableCellRenderer 子类化,但是我不确定在 getTableCellRendererComponent() 方法中究竟需要什么。

    请参阅Table Format Rendering,了解执行此操作的简单方法。这种方法只是覆盖了渲染器的setValue(...) 方法。

    我很确定我必须继承 DefaultCellEditor 才能使编辑和错误检查正常工作。

    这是我在某个论坛上找到的一些创建自定义 IntegerEditor 的旧代码。第一列使用默认的整数编辑器,第二列使用自定义编辑器。

    import java.awt.*;
    import java.util.EventObject;
    import javax.swing.*;
    import javax.swing.border.*;
    import javax.swing.table.*;
    import javax.swing.text.*;
    import java.text.*;
    import java.awt.event.*;
    public class TableIntegerEditor
    {
        static class IntegerEditor extends DefaultCellEditor
        {
            JFormattedTextField ftf;
            NumberFormat integerFormat;
            private Integer minimum, maximum;
            private boolean DEBUG = false;
    
            public IntegerEditor(int min, int max)
            {
                super(new JFormattedTextField());
    
                setClickCountToStart(2);
    
                ftf = (JFormattedTextField)getComponent();
                ftf.setBorder(new LineBorder(Color.BLACK));
                minimum = new Integer(min);
                maximum = new Integer(max);
    
                //Set up the editor for the integer cells.
                integerFormat = NumberFormat.getIntegerInstance();
                NumberFormatter intFormatter = new NumberFormatter(integerFormat);
                intFormatter.setFormat(integerFormat);
                intFormatter.setMinimum(minimum);
                intFormatter.setMaximum(maximum);
    
                ftf.setFormatterFactory(new DefaultFormatterFactory(intFormatter));
                ftf.setValue(minimum);
                ftf.setHorizontalAlignment(JTextField.TRAILING);
                ftf.setFocusLostBehavior(JFormattedTextField.PERSIST);
    
                //React when the user presses Enter while the editor is
                //active.  (Tab is handled as specified by
                //JFormattedTextField's focusLostBehavior property.)
                ftf.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "check");
    
                ftf.getActionMap().put("check", new AbstractAction()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        if (!ftf.isEditValid())  //The text is invalid.
                        {
                            if (userSaysRevert())
                            {
                                ftf.postActionEvent(); //inform the editor
                            }
                        }
                        else
                            try
                            {
                                ftf.commitEdit();     //so use it.
                                ftf.postActionEvent(); //stop editing
                            }
                            catch (java.text.ParseException exc) { }
                    }
                });
            }
    
            @Override
            public boolean isCellEditable(EventObject event)
            {
                JTable table = (JTable)event.getSource();
                return true;
            }
    
            //Override to invoke setValue on the formatted text field.
            public Component getTableCellEditorComponent(
                JTable table, Object value, boolean isSelected, int row, int column)
            {
                 JFormattedTextField ftf = (JFormattedTextField)super.getTableCellEditorComponent(
                    table, value, isSelected, row, column);
                 ftf.setValue(value);
    
                 return ftf;
            }
    
            //Override to ensure that the value remains an Integer.
            public Object getCellEditorValue()
            {
                JFormattedTextField ftf = (JFormattedTextField)getComponent();
                Object o = ftf.getValue();
                if (o instanceof Integer)
                {
                    return o;
                }
                else if (o instanceof Number)
                {
                    return new Integer(((Number)o).intValue());
                }
                else
                {
                    try
                    {
                        return integerFormat.parseObject(o.toString());
                    }
                    catch (ParseException exc)
                    {
                        System.err.println("getCellEditorValue: can't parse o: " + o);
                        return null;
                    }
                }
            }
    
            //Override to check whether the edit is valid,
            //setting the value if it is and complaining if
            //it isn't.  If it's OK for the editor to go
            //away, we need to invoke the superclass's version
            //of this method so that everything gets cleaned up.
            public boolean stopCellEditing()
            {
                JFormattedTextField ftf = (JFormattedTextField)getComponent();
    
                if (ftf.isEditValid())
                {
                    try
                    {
                        ftf.commitEdit();
                    }
                    catch (java.text.ParseException exc) { }
    
                }
                else
                {
                    if (!userSaysRevert())  //user wants to edit
                    {
                        return false; //don't let the editor go away
                    }
                 }
    
                 return super.stopCellEditing();
            }
    
            /**
             * Lets the user know that the text they entered is
             * bad. Returns true if the user elects to revert to
             * the last good value.  Otherwise, returns false,
             * indicating that the user wants to continue editing.
             */
            protected boolean userSaysRevert() {
                 Toolkit.getDefaultToolkit().beep();
                 ftf.selectAll();
                 Object[] options = {"Edit",
                                            "Revert"};
                 int answer = JOptionPane.showOptionDialog(
                      SwingUtilities.getWindowAncestor(ftf),
                      "The value must be an integer between "
                      + minimum + " and "
                      + maximum + ".\n"
                      + "You can either continue editing "
                      + "or revert to the last valid value.",
                      "Invalid Text Entered",
                      JOptionPane.YES_NO_OPTION,
                      JOptionPane.ERROR_MESSAGE,
                      null,
                      options,
                      options[1]);
    
                 if (answer == 1) { //Revert!
                      ftf.setValue(ftf.getValue());
                 return true;
                 }
            return false;
            }
    
    
        }
    
        private static void createAndShowGUI()
        {
            String[] columnNames = {"String", "Integer", "Integer2"};
            Object[][] data =
            {
                {"a", new Integer(1), new Integer(10)},
                {"b", new Integer(2), new Integer(20)},
                {"c", new Integer(3), new Integer(30)}
            };
    
            JTable table = new JTable(data, columnNames)
            {
                public Class getColumnClass(int column)
                {
                    if (column == 0)
                        return String.class;
                    else
                        return Integer.class;
                }
    
            };
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            JScrollPane scrollPane = new JScrollPane( table );
    
            table.getColumnModel().getColumn(2).setCellEditor( new IntegerEditor(0, 200) );
    
            DefaultCellEditor editor = (DefaultCellEditor)table.getDefaultEditor(Integer.class);
            JComponent border = (JComponent)editor.getComponent();
            border.setBorder( BorderFactory.createLineBorder( Color.RED ) );
    
            JFrame frame = new JFrame("Integer Editor");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add( scrollPane );
            frame.setLocationByPlatform( true );
            frame.pack();
            frame.setVisible( true );
        }
    
        public static void main(String[] args)
        {
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    createAndShowGUI();
                }
            });
        }
    
    
    }
    

    如果您只想使用默认的 Double 编辑器,则只需将列类更改为您的列的 Double.class。如果您需要特殊编辑,则需要根据您的双重要求自定义 IntegerEditor。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-07
      • 2011-03-25
      • 2017-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      相关资源
      最近更新 更多