试图使用键监听器

时间:2014-04-11 02:37:22

标签: java string awt substring keylistener

我有一个实现keyListener的程序。我想要做的只是按下数字,退格键,十进制键和后退箭头键。一切正常,除非我按下后退箭头键,它删除了我输入的数字

public void keyReleased(KeyEvent e) {

        try{
if(!Character.isDigit(e.getKeyChar()) && e.getKeyChar() != '.' && e.getKeyChar() != e.VK_BACK_SPACE && e.getKeyChar() != KeyEvent.VK_LEFT){

                String input = inputIncome.getText();
                inputIncome.setText(input.substring(input.length()-1));  
            }

        }
        catch(Exception arg){

        }`

1 个答案:

答案 0 :(得分:3)

KeyListener规则......

  • 请勿将KeyListener用于不需要激活焦点的组件,即使这样,也请使用Key Bindings
  • 请勿在文字组件上使用KeyListener,而是使用DocumentFilter代替

基于您似乎正在更改内容,我认为是JTextField或文本组件的事实,您应该使用DocumentFilter来过滤已发送给字段Document,例如......

import java.awt.EventQueue;
import java.awt.GridBagLayout;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;

public class DocumentFilterExample {

    public static void main(String[] args) {
        new DocumentFilterExample();
    }

    public DocumentFilterExample() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JTextField field = new JTextField(10);
                ((AbstractDocument)field.getDocument()).setDocumentFilter(new DecimalDocumentFilter());

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new GridBagLayout());
                frame.add(field);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DecimalDocumentFilter extends DocumentFilter {

        @Override
        public void insertString(DocumentFilter.FilterBypass fb, int offset,
                String text, AttributeSet attr)
                throws BadLocationException {

            Document doc = fb.getDocument();
            boolean hasDot = doc.getText(0, doc.getLength()).contains(".");
            StringBuilder buffer = new StringBuilder(text);
            for (int i = buffer.length() - 1; i >= 0; i--) {
                char ch = buffer.charAt(i);
                if (!Character.isDigit(ch)) {
                    if ((ch == '.' && !hasDot)) {
                        hasDot = true;
                    } else {
                        buffer.deleteCharAt(i);
                    }
                }
            }
            super.insertString(fb, offset, buffer.toString(), attr);
        }

        @Override
        public void replace(DocumentFilter.FilterBypass fb,
                int offset, int length, String string, AttributeSet attr) throws BadLocationException {
            if (length > 0) {
                fb.remove(offset, length);
            }
            insertString(fb, offset, string, attr);
        }
    }

}

这基于examples here

以这种方式不使用KeyListener有很多原因,例如......

  • 您不能保证激活侦听器的顺序,事件可能会在到达您之前被消耗,或者内容尚未添加到字段Document
  • 中。
  • 它没有考虑将文字粘贴到字段中时会发生什么
  • 当您尝试更改文档时,它可能会导致更改异常...

仅举几例