【问题标题】:Java Textfield set char length [duplicate]Java Textfield设置字符长度[重复]
【发布时间】:2014-11-05 20:07:53
【问题描述】:

在java中似乎没有办法限制长度。我查看了其他示例,人们创建了单独的类等。

我很好奇我们是否可以使用动作事件而不使用其他类来做到这一点。

这是我目前所拥有的。

   txtTest.addKeyListener(new KeyAdapter()
   public void keyPressed(KeyEvent e)
        {
            int MAX_LEN = 5;
            char c = e.getKeyChar();
            int len = txtTest.getText().length();
            if(len < MAX_LEN)
            {
                return;
            }else
            {
                Logging.info("TOOO LONG");
            }

        }
    });

所以我到了如果我输入的文本长度超过 5 个字符的地步。是否有任何事件可以触发,所以如果他们输入 6 个字符,它将被删除?例如模仿退格键或删除键?

【问题讨论】:

    标签: java swing textfield


    【解决方案1】:

    抱歉,这是一个非常脆弱的解决方案,您应该尽可能避免在文本组件上使用 KeyListener。例如,当用户试图复制和粘贴文本时会发生什么?恐怕在那种情况下,您的代码会失败。避免使用 KeyListeners 还有其他更深层次的原因,但底线是使用 DocumentFilter 会更好。

    例如

    import javax.swing.*;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.Document;
    import javax.swing.text.DocumentFilter;
    import javax.swing.text.PlainDocument;
    
    
    @SuppressWarnings("serial")
    public class TextTestGui extends JPanel  {
       private JTextField limitedField = new JTextField(10);
    
       public TextTestGui() {
          add(limitedField);
          PlainDocument doc = (PlainDocument) limitedField.getDocument();
          doc.setDocumentFilter(new MyDocFilter(5));;
       }
    
       private class MyDocFilter extends DocumentFilter {
    
          private int limit;
    
          public MyDocFilter(int limit) {
             this.limit = limit;
          }
    
          @Override
          public void insertString(FilterBypass fb, int offset, String string,
                AttributeSet attr) throws BadLocationException {
             Document innerDoc = fb.getDocument();
             StringBuilder sb = new StringBuilder(innerDoc.getText(0, innerDoc.getLength()));
             sb.insert(offset, string);
             if (textOK(sb.toString())) {
                super.insertString(fb, offset, string, attr);
             }
          }
    
          @Override
          public void replace(FilterBypass fb, int offset, int length, String text,
                AttributeSet attrs) throws BadLocationException {
             Document innerDoc = fb.getDocument();
             StringBuilder sb = new StringBuilder(innerDoc.getText(0, innerDoc.getLength()));
             int start = offset; 
             int end = offset + length;
             sb.replace(start, end, text);
             if (textOK(sb.toString())) {
                super.replace(fb, offset, length, text, attrs);
             }
          }
    
          @Override
          public void remove(FilterBypass fb, int offset, int length)
                throws BadLocationException {
             super.remove(fb, offset, length);
          }
    
          private boolean textOK(String text) {
             if (text.length() <= limit) {
                return true;
             }
             return false;
          }
       }
    
       private static void createAndShowGui() {
          TextTestGui mainPanel = new TextTestGui();
    
          JFrame frame = new JFrame("TextTestGui");
          frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          frame.getContentPane().add(mainPanel);
          frame.pack();
          frame.setLocationByPlatform(true);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
             public void run() {
                createAndShowGui();
             }
          });
       }
    }
    

    【讨论】:

    • 如果 getText() 的前 5 个字符的子字符串被子字符串化并使用 setText 设置怎么办?
    • 有没有办法在同一个类中使用 DocumentFilter?
    • @user1158745:当然。只需创建一个匿名内部类或私有内部类,就像为 ActionListener 所做的一样。
    • @Compass:它将严格按照您编写的方式运行,不多也不少。
    • 您能给我举个例子,如何将 DoucmentFilter 与匿名内部类一起使用吗?
    【解决方案2】:

    这是使用 keyListener 的一种方式:

    txtTest.addKeyListener(new KeyAdapter(){
        public void keyPressed(KeyEvent e)
        {
            char[] letters = txtTest.getText().toCharArray();
            if(txtTest.getText().length() < 5)
            {
                return;
            }else
            {
                txtTest.setText(""+letters[0]+letters[1]+letters[2]+letters[3]+letters[4]);
            }
        }
    });
    

    但是你可以用一个while循环来做到这一点:

    public void Update(){
        while(true){
            if(txtTest.getText() != null){
                if(!(txtTest.getText().length() < 5))
                {
                    char[] letters = txtTest.getText().toCharArray();
                    txtTest.setText(""+letters[0]+letters[1]+letters[2]+letters[3]+letters[4]);
                }
            }
        }
    }
    

    不幸的是,它处理起来有点太快了,所以你需要调节更新速度,这变得很复杂。

    【讨论】:

    • 再次,1) 当有人使用复制和粘贴将文本添加到使用您的解决方案的 JTextField 时会发生什么? 2)您是否测试过您的第二个解决方案?你在 Swing 事件线程上做这个while (true) 循环吗? GUI 还能用吗?
    猜你喜欢
    • 2012-07-14
    • 2018-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 2016-06-10
    • 2016-09-18
    相关资源
    最近更新 更多