自定义JTextField(JCurrencyField) [英] make custom JTextField (JCurrencyField)

查看:146
本文介绍了自定义JTextField(JCurrencyField)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



JCurrencyField是一个普通的JTextField,但它不能用于我的程序中,使用它的JCurrencyField,我几乎完成创建它,但我遇到了一个问题。接受任何不是数字或小数点的字符,并且我为这个JCurrencyField做了一些规定:


  • 用户不能插入多个小数点

  • 用户不能插入超过两位数小数点。


    我遇到的问题是无法在小数点前插入任何数字,如果有两位数



    这是我的代码:

      import javax.swing中*。 
    import javax.swing.text。*;
    public class JCurrencyField extends JTextField
    {
    public JCurrencyField()
    {
    ((AbstractDocument)getDocument())。setDocumentFilter(new NumberOnlyFilter());


    private class NumberOnlyFilter extends DocumentFilter
    {
    public void insertString(DocumentFilter.FilterBypass fb,int offset,
    String text,AttributeSet attr)throws BadLocationException
    {
    if(!containsOnlyNumbers(text))return;
    fb.insertString(offset,text,attr);

    $ b $ public void replace(DocumentFilter.FilterBypass fb,int offset,int length,
    String text,AttributeSet attr)throws BadLocationException
    {
    if (!containsOnlyNumbers(text))return;
    fb.replace(offset,length,text,attr);

    $ b $ **
    *这个方法检查一个String是否只包含数字
    * /
    public boolean containsOnlyNumbers(String str)
    {

    //不能只包含数字,如果它为空或空...
    if(str == null || str.length()== 0)return false ;


    int counter = 0;
    for(int i = 0; i< getText().length(); i ++)
    {
    if(counter> 1)return false;
    if(getText()。charAt(i)=='。')
    {
    counter ++;
    }
    }

    int fp_counter = 0;
    int fp_index = -1;
    for(int i = 0; i< str.length(); i ++)
    {
    if(counter> = 1)break;
    if(str.charAt(i)=='。')
    {
    fp_counter ++;
    fp_index = i;



    if(fp_counter> 1)return false;

    if(str.length()> fp_index + 3)返回false;
    $ b $ if(counter> = 1)
    {
    for(int i = 0; i< getText()。length(); i ++)
    {
    if(getText()。charAt(i)=='。')counter ++;



    (int j = 0; j {
    if(counter> = 1&&(str.charAt(j)=='。'))return false;
    }

    int index = 0;
    布尔型fp_Flag = false;
    int sp_count = 0; ();
    for(int k = 0; k {
    if(getText()。charAt(k)=='。')
    {
    index = k;
    fp_Flag = true;
    }
    if(fp_Flag)sp_count ++;
    if(sp_count> 2)return false;
    }

    // if(fp_Flag&& str.length()> 2)return false; (fp_Flag&& index + 1< getText().length()&& str.length()> 1)返回false;
    // if(index + 2< getText().length()&& fp_Flag)返回false; (int l = 0; l {

    //

    $ b //如果我们发现一个非数字我们返回false。
    if(str.charAt(l)=='。')continue;
    if(!Character.isDigit(str.charAt(l)))
    return false;
    }

    return true;





    $ p

    测试程序:

      private class NumberOnlyFilter extends DocumentFilter {
    public void insertString(DocumentFilter.FilterBypass fb,int offset,
    String text,AttributeSet attr )抛出BadLocationException {
    StringBuilder sb = new StringBuilder();
    sb.append(fb.getDocument()。getText(0,fb.getDocument()。getLength()));
    sb.insert(offset,text);
    if(!containsOnlyNumbers(sb.toString()))
    return;
    fb.insertString(offset,text,attr);

    $ b $ public void replace(DocumentFilter.FilterBypass fb,int offset,
    int length,String text,AttributeSet attr)
    抛出BadLocationException {
    StringBuilder sb = new StringBuilder();
    sb.append(fb.getDocument()。getText(0,fb.getDocument()。getLength()));
    sb.replace(offset,offset + length,text);
    if(!containsOnlyNumbers(sb.toString()))
    return;
    fb.replace(offset,length,text,attr);



    $ b

    您将需要更改您的containsOnlyNumbers方法来说明这些更改。

    编辑1

    这可以使用toto的正则表达式轻松完成:

      private boolean containsOnlyNumbers(String text){
    Pattern pattern = Pattern.compile(\\ d *(\\.\\\ \\d {0,2}))?;
    Matcher matcher = pattern.matcher(text);
    boolean isMatch = matcher.matches();
    返回isMatch;
    }


    I making a JCurrencyField to use it in my program, I almost finished creating it but I've faced an issue.

    JCurrencyField is a normal JTextField but it cannot accept any character that is not a number or decimal point . and I made some specifications for this JCurrencyField:

    • The user cannot insert more than one decimal point ..
    • The user cannot insert more than two digits after the decimal point.

    The issue I've faced was not being able to insert any digits before the decimal point if there are two digits after the decimal point.

    Here is my code:

    import javax.swing.*;
    import javax.swing.text.*;
    public class JCurrencyField extends JTextField
    {
        public JCurrencyField()
        {
            ((AbstractDocument)getDocument()).setDocumentFilter(new NumberOnlyFilter());
        }
    
        private class NumberOnlyFilter extends DocumentFilter
        {
            public void insertString(DocumentFilter.FilterBypass fb, int offset,   
            String text, AttributeSet attr) throws BadLocationException
            {
                if(!containsOnlyNumbers(text)) return;
                fb.insertString(offset, text, attr);   
            }    
    
            public void replace(DocumentFilter.FilterBypass fb, int offset, int length,   
            String text, AttributeSet attr) throws BadLocationException
            {
                if(!containsOnlyNumbers(text)) return;
                fb.replace(offset, length, text, attr);
            }
    
            /**
            * This method checks if a String contains only numbers
            */
            public boolean containsOnlyNumbers(String str)
            {
    
                //It can't contain only numbers if it's null or empty...
                if (str == null || str.length() == 0) return false;
    
    
                int counter = 0;
                for(int i = 0; i < getText().length(); i++)
                {
                    if(counter > 1) return false;
                    if(getText().charAt(i) == '.')
                    {
                        counter++;
                    }
                }
    
                int fp_counter = 0;
                int fp_index = -1;
                for(int i = 0; i < str.length(); i++)
                {
                    if(counter >= 1) break;
                    if(str.charAt(i) == '.')
                    {
                        fp_counter++;
                        fp_index = i;
                    }
                }
    
                if(fp_counter > 1) return false;
    
                if(str.length() > fp_index + 3) return false;
    
                if(counter >= 1)
                {
                    for(int i = 0; i < getText().length(); i++)
                    {
                        if(getText().charAt(i) == '.') counter++;
                    }
                }
    
                for (int j = 0; j < str.length(); j++)
                {
                    if(counter >= 1 && (str.charAt(j) == '.')) return false;
                }
    
                int index = 0;
                boolean fp_Flag = false;
                int sp_count = 0;
                for(int k = 0; k < getText().length(); k++)
                {
                    if(getText().charAt(k) == '.')
                    {
                        index = k;
                        fp_Flag = true;
                    }
                    if(fp_Flag) sp_count++;
                    if(sp_count > 2) return false;
                }
    
                //if(fp_Flag && str.length() > 2) return false;
                if(fp_Flag && index + 1 < getText().length() && str.length() > 1) return false;
                //if(index + 2 < getText().length() && fp_Flag) return false;
    
    
                for (int l = 0; l < str.length(); l++)
                {
    
                    //If we find a non-digit character we return false.
                    if(str.charAt(l) == '.') continue;
                    if(!Character.isDigit(str.charAt(l)))
                    return false;
                }
    
                return true;
            }
        }
    }
    

    Test Program:

    import java.awt.*;
    import java.util.*;
    import javax.swing.*;
    import javax.swing.border.*;
    public class Test extends JFrame
    
    {
        private JCurrencyField txt = new JCurrencyField();
        public Test()
        {
            super("Test...");
            setDefaultCloseOperation(EXIT_ON_CLOSE);
            try{ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
            catch(Exception e){ System.out.println("Unable to load Windows look and feel");}
            setPreferredSize(new Dimension(300, 100));
            ((JPanel) getContentPane()).setBorder(new EmptyBorder(13, 13, 13, 13) );
            setLayout(new FlowLayout());
            txt.setPreferredSize(new Dimension(100,30));
            add(txt);
            pack();
            setLocationRelativeTo(null);
            setVisible(true);
            setResizable(false);
        }
        public static void main(String[] args)
        {
            new Test();
        }
    }
    

    could you please help me to solve this issue?

    解决方案

    You're testing the wrong string in your DocumentFilter.

    You shouldn't be testing the text String but rather the String built from text and Document obtained from the FilterBypass parameter since this is the String that you want to see if it fulfills the criteria. For instance, not this:

        public void insertString(DocumentFilter.FilterBypass fb, int offset,   
        String text, AttributeSet attr) throws BadLocationException
        {
            if(!containsOnlyNumbers(text)) return;
            fb.insertString(offset, text, attr);   
        }    
    
        public void replace(DocumentFilter.FilterBypass fb, int offset, int length,   
        String text, AttributeSet attr) throws BadLocationException
        {
            if(!containsOnlyNumbers(text)) return;
            fb.replace(offset, length, text, attr);
        }
    

    But rather this:

       private class NumberOnlyFilter extends DocumentFilter {
          public void insertString(DocumentFilter.FilterBypass fb, int offset,
                   String text, AttributeSet attr) throws BadLocationException {
             StringBuilder sb = new StringBuilder();
             sb.append(fb.getDocument().getText(0, fb.getDocument().getLength()));
             sb.insert(offset, text);
             if (!containsOnlyNumbers(sb.toString()))
                return;
             fb.insertString(offset, text, attr);
          }
    
          public void replace(DocumentFilter.FilterBypass fb, int offset,
                   int length, String text, AttributeSet attr)
                   throws BadLocationException {
             StringBuilder sb = new StringBuilder();
             sb.append(fb.getDocument().getText(0, fb.getDocument().getLength()));
             sb.replace(offset, offset + length, text);
             if (!containsOnlyNumbers(sb.toString()))
                return;
             fb.replace(offset, length, text, attr);
          }
    

    You will need to make changes to your containsOnlyNumbers method to account for these changes.

    Edit 1
    And this can be easily done using toto's regex:

      private boolean containsOnlyNumbers(String text) {
         Pattern pattern = Pattern.compile("\\d*(\\.\\d{0,2})?");
         Matcher matcher = pattern.matcher(text);
         boolean isMatch = matcher.matches();
         return isMatch;
      }
    

    这篇关于自定义JTextField(JCurrencyField)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

      import java.awt。*; 
    import java.util。*;
    import javax.swing。*;
    import javax.swing.border。*;
    public class Test扩展JFrame

    {
    private JCurrencyField txt = new JCurrencyField();
    public Test()
    {
    super(Test ...);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
    catch(Exception e){System.out.println(Unable to load Windows look and feel);}
    setPreferredSize(new Dimension(300,100));
    ((JPanel)getContentPane())。setBorder(new EmptyBorder(13,13,13,13));
    setLayout(new FlowLayout());
    txt.setPreferredSize(new Dimension(100,30));
    add(txt);
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
    setResizable(false);

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


    $ / code $ / pre

    你能帮我解决这个问题吗? / p>

    解决方案

    您正在测试DocumentFilter中的错误字符串。

    您不应该测试文本字符串,而是从文本和从FilterBypass参数获取的文档构建的字符串,因为这是您要查看的字符串符合标准。例如,不是这样的:

    pre $ public $ insertString(DocumentFilter.FilterBypass fb,int offset,
    String text,AttributeSet attr)抛出BadLocationException
    {
    if(!containsOnlyNumbers(text))return;
    fb.insertString(offset,text,attr);

    $ b $ public void replace(DocumentFilter.FilterBypass fb,int offset,int length,
    String text,AttributeSet attr)throws BadLocationException
    {
    if (!containsOnlyNumbers(text))return;
    fb.replace(offset,length,text,attr);
    }

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆