代码之家  ›  专栏  ›  技术社区  ›  Roy Ash

从jTextField获取最终文本预览

  •  0
  • Roy Ash  · 技术社区  · 4 年前

    我正在努力创造 JTextField 此支票只能接受双精度(包括科学符号):

    abstract class DoubleKeyAdapter extends KeyAdapter
    {
        @Override
        public void KeyTyped(KeyEvent e)
        {
            if (!(((JTextField) e.getSource()).getText() + e.getKeyChar()).matches(“[+-]?\\d*(\\.\\d*)?([eE][+-]?\\d*)?”))
                e.consume();
        }
    
        @Override
        public abstract void KeyReleased(KeyEvent e);
    }
    

    问题是当我尝试添加 - - 因此,我的问题是:

    1. 在整个文本出现在文本字段中之前,有没有办法获得它的预览?
    2. 有没有一种方法可以创造 (或其延伸)这样做更好吗?
    0 回复  |  直到 4 年前
        1
  •  2
  •   camickr    4 年前

    你可以使用 DocumentFilter

    它允许您在将文本插入文档之前进行编辑。

    import java.awt.*;
    import javax.swing.*;
    import javax.swing.text.*;
    
    public class DoubleFilter extends DocumentFilter
    {
        @Override
        public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributes)
            throws BadLocationException
        {
            replace(fb, offset, 0, text, attributes);
        }
    
        @Override
        public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attributes)
            throws BadLocationException
        {
            //  In case someone tries to clear the Document by using setText(null)
    
            if (text == null)
                text = "";
    
            //  Build the text string assuming the replace of the text is successfull
    
            Document doc = fb.getDocument();
            StringBuilder sb = new StringBuilder();
            sb.append(doc.getText(0, doc.getLength()));
            sb.replace(offset, offset + length, text);
    
            if (validReplace(sb.toString()))
                super.replace(fb, offset, length, text, attributes);
            else
                Toolkit.getDefaultToolkit().beep();
        }
    
        private boolean validReplace(String text)
        {
            //  In case setText("") is used to clear the Document
    
            if (text.isEmpty())
                return true;
    
            //  Verify input is a Double
    
            try
            {
                Double.parseDouble( text );
                return true;
            }
            catch (NumberFormatException e)
            {
                return false;
            }
        }
    
        private static void createAndShowGUI()
        {
            JTextField textField = new JTextField(10);
            AbstractDocument doc = (AbstractDocument) textField.getDocument();
            doc.setDocumentFilter( new DoubleFilter() );
            textField.setText("123");
            textField.setText("123567");
            textField.setText(null);
    
            JFrame frame = new JFrame("Integer Filter");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout( new java.awt.GridBagLayout() );
            frame.add( textField );
            frame.setSize(220, 200);
            frame.setLocationByPlatform( true );
            frame.setVisible( true );
        }
    
        public static void main(String[] args) throws Exception
        {
            EventQueue.invokeLater( () -> createAndShowGUI() );
    /*
            EventQueue.invokeLater(new Runnable()
            {
                public void run()
                {
                    createAndShowGUI();
                }
            });
    */
        }
    
    }
    

        2
  •  0
  •   Roy Ash    4 年前

    我的解决方案灵感来自@camickr, 增加了两种方法: getDouble() setDouble()

    import javax.swing.*;
    import javax.swing.text.*;
    import java.util.regex.Pattern;
    
    public class JDoubleField extends JTextField
    {
        private static final DocumentFilter doubleFilter = new DocumentFilter()
        {
            private final Pattern pattern = Pattern.compile("[+-]?(NaN|Infinity|\\d*(\\.\\d*)?((?<=\\d\\.?)[eE][+-]?\\d*)?)");
    
            @Override
            public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException
            {
                replace(fb, offset, 0, string, attr);
            }
    
            @Override
            public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException
            {
                if (text == null || pattern.matcher(new StringBuilder(fb.getDocument().getText(0, fb.getDocument().getLength()))
                        .replace(offset, offset + length, text))
                        .matches())
                    super.replace(fb, offset, length, text, attrs);
            }
        };
    
        public double getDouble()
        {
            try
            {
                return Double.parseDouble(getText());
            } catch (NumberFormatException ignored)
            {
                return Double.NaN;
            }
        }
    
        public void setDouble(double num)
        {
            setText(String.valueOf(num));
        }
    
        public JDoubleField()
        {
            this(0);
        }
    
        public JDoubleField(double num)
        {
            this(String.valueOf(num));
        }
    
        public JDoubleField(double num, int columns)
        {
            this(String.valueOf(num), columns);
        }
    
        public JDoubleField(Document doc, double num, int columns)
        {
            this(doc, String.valueOf(num), columns);
        }
    
        public JDoubleField(int columns)
        {
            this(null, columns);
        }
    
        public JDoubleField(String text)
        {
            this(text, 0);
        }
    
        public JDoubleField(String text, int columns)
        {
            this(null, text, columns);
        }
    
        public JDoubleField(Document doc, String text, int columns)
        {
            super(doc, null, columns);
            ((AbstractDocument) getDocument()).setDocumentFilter(doubleFilter);
            if (text != null)
                setText(text);
        }
    }