JTextField,使用文档过滤器过滤整数和句点 [英] JTextField, using Document Filter to filter integers and periods

查看:88
本文介绍了JTextField,使用文档过滤器过滤整数和句点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑-在帖子的末尾添加了我们能够实现的答案

EDIT - added at then end of the post the answer we were able to achieve

这是我在SO上的第一篇文章,所以我希望我能问对所有问题!

This is my first post in SO, so i hope i can ask everything right!

尽管发布了类似的问题,但我仍然搜索并没有找到答案,所以我希望这不是重新发布.

I searched and didn't quite find a answer to my question despite similar questions being posted, so i hope this isn't a repost.

ai就是这样,这是一个小型应用程序,它使用JTextField来接收用户的输入,并且最重要的是,我有一个DocumentFilter,因此用户只能输入整数和句点以便接收表示权重的值

This is what a i got, a small application that uses JTextField to receive user's input and on top of that i have a DocumentFilter so the user can only input integers and a period in order to receive values that represent weight.

我的问题是,我的DocumentFilter无法过滤复制粘贴的"文本,并且无法过滤选定的文本.

My problem is, with my DocumentFilter I'm not being able to filter "copy pasted" text and i can't filter a selected text removal.

这是过滤器的代码

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

/**
* The Class IntAndDotFilter.
*/
public class IntAndDotFilter extends DocumentFilter {

/** The period counter. */
private int periodCounter = 0;

/** The number counter. */
private int numberCounter = 0;

private boolean canRemove = true;

public void setCanRemove(boolean canRemove) {
    this.canRemove = canRemove;
}

@Override
public void replace(FilterBypass fb, int offset, int length, String text,
        AttributeSet attrs) throws BadLocationException {

    if (periodCounter == 0) { // If there is no . on the text
        if (text.matches("\\.")) { // Checks if the input is a dot
            super.replace(fb, offset, length,
                    text.replaceAll("[^0-9.]", ""), attrs);
            periodCounter++; // If it is, inserts it and saves that info
        } else {
            super.replace(fb, offset, length,
                    text.replaceAll("[^0-9]", ""), attrs);
            // If not, checks if the input is a digit
            // and inserts if it is
        }
    } else { // If there is already a .
        if (text.matches("\\.")) { // Checks if the input is another .
            super.replace(fb, offset, length,
                    text.replaceAll("[^0-9]", ""), attrs);
            // If it is, filters so that cannot be more than one .
        } else {
            if (text.matches("[0-9]")) { // Checks if it's a digit
                if (numberCounter != 2) {
                    super.replace(fb, offset, length,
                            text.replaceAll("[^0-9]", ""), attrs);
                    numberCounter++;
                    // If yes, and if that is only the second one (0.00)
                    // inserts and
                    // saves the info that there are digits after the 1st .
                    // for removal purposes
                } else {
                    super.replace(fb, offset, length,
                            text.replaceAll(".", ""), attrs);
                    // if it is the third+ digit after . , doesn't allow the
                    // input
                }
            } else {
                super.replace(fb, offset, length, text.replaceAll(".", ""),
                        attrs);
                // Not being a digit, doesn't allow the
                // insertion of the given input
            }
        }
    }
}

@Override
public void remove(FilterBypass fb, int offset, int length)
        throws BadLocationException {

    if (canRemove) {
        if (periodCounter == 1) { // If there is a . in the text
            if (numberCounter != 0) { // and If there are digits after the .
                numberCounter--; // It means you'r removing a digit, so it
                                    // saves
                                    // that info
                super.remove(fb, offset, length); // And removes it
            } else { // If there are no digits it means you'r removing a .
                periodCounter--; // It saves that info allowing a new . to
                                    // be
                                    // inserted
                super.remove(fb, offset, length); // and removes it
            }
        } else { // If there is no . in the text there are no problems
            super.remove(fb, offset, length); // so it just removes whatever
                                                // there is (digit)
        }
    } else {

    }
}
}

insertString方法的功能与replace方法相同,因此我省略了它,但在应用程序中已实现.

the insertString method does the same has the replace method so i left it out, but in the application it's implemented.

提前感谢您的时间!

编辑-另外,它现在还具有一个过滤器来限制高度输入

EDIT - Plus it now has a filter to restrain the height input too

public class IntAndDotFilter extends DocumentFilter {

/** The Constant _maxCharacters. */
private static final int _maxCharacters = 10;

/** The _is weight. */
private Boolean _isWeight = null;


public IntAndDotFilter(Boolean isWeight) {
    super();
    _isWeight = isWeight;
}

public void replace(FilterBypass fb, int offset, int length, String string,
        AttributeSet attr) throws BadLocationException {

    String text = fb.getDocument().getText(0, fb.getDocument().getLength());
    text += string;

    if (_isWeight) {
        if ((fb.getDocument().getLength() + string.length() - length) <= _maxCharacters
                && text.matches("^[1]?[0-9]{1,2}([.][0-9]{0,2})?$")) {
            super.replace(fb, offset, length, string, attr);
        } else {
            Toolkit.getDefaultToolkit().beep();
        }
    } else {
        if ((fb.getDocument().getLength() + string.length() - length) <= _maxCharacters
                && text.matches("^([1]([.][0-9]{0,2})?)|([2]([.][0-5]?)?)$")) {
            super.replace(fb, offset, length, string, attr);
        } else {
            Toolkit.getDefaultToolkit().beep();
        }
    }
}

@Override
public void remove(FilterBypass fb, int offset, int length)
        throws BadLocationException {

    String text = fb.getDocument().getText(0, fb.getDocument().getLength());

    if (_isWeight) {
        if (text.matches("^[1]?[0-9]{1,2}([.][0-9]{0,2})?$")) {
            super.remove(fb, offset, length);
        } else {
            Toolkit.getDefaultToolkit().beep();
        }
    } else {
        if (text.matches("^([1]([.][0-9]{0,2})?)|([2]([.][0-5]?)?)$")) {
            super.remove(fb, offset, length);
        } else {
            Toolkit.getDefaultToolkit().beep();
        }
    }
}

推荐答案

您正在使过滤变得更加复杂.对于插入(如果代码相同,则为替换),可能由于\\.检查而无法输入.您将只能粘贴一个句点,因为这就是您要检查的句点.至于删除,以下建议将适用.

You're making the filtering more complicated than it has to be. For inserting (if the code is same is replace), you are not able to enter probably because of the \\. check. You will only be able to paste a period, as that's what you are checking for. As for the remove, the suggestion below will apply.

为简化起见,您应该只获取文档的整个文本,然后使用正则表达式检查整个文档字符串是否与正则表达式匹配.它比您要尝试的要简单得多.您可以在此处很好地解释过滤过程.

To simplify things, you should just get the entire text of the document, then use regex to check if the entire document string matches the regex. It's much simpler than what you are trying to do. You can get a good explanation of the filtering process here.

这里是一个示例,仅使用insertString和replace.对于删除,没有什么不同,只需获取文本,然后检查其是否与正则表达式匹配.我从上面链接的答案中摘取了一部分示例.场景是,OP需要最大字符数,并且只允许小数点后一位.这就是正则表达式匹配的东西.但也可以匹配您正在键入或插入的任何内容,例如00 00. 00.0

Here's an example, using just insertString and replace. For the remove, it's no different, just get the text, and check if it matches a regex. I took part of the example from the answer in the link above. The scenario was that the OP wanted max charcters, along with only one decimal place allowed. That's what the regex matches. But could also match anything as you're typing or inserting such as 00 00. 00.0

import java.awt.GridBagLayout;
import java.awt.Toolkit;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;

public class FilterDemo {

    public FilterDemo() {
        JFrame frame = new JFrame();
        frame.setLayout(new GridBagLayout());
        frame.setSize(300, 300);
        frame.add(createFilteredField());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

    }

    public JTextField createFilteredField() {
        JTextField field = new JTextField();
        AbstractDocument document = (AbstractDocument) field.getDocument();
        final int maxCharacters = 10;
        document.setDocumentFilter(new DocumentFilter() {
            public void replace(FilterBypass fb, int offs, int length,
                    String str, AttributeSet a) throws BadLocationException {

                String text = fb.getDocument().getText(0,
                        fb.getDocument().getLength());
                text += str;
                if ((fb.getDocument().getLength() + str.length() - length) <= maxCharacters
                        && text.matches("^[0-9]+[.]?[0-9]{0,1}$")) {
                    super.replace(fb, offs, length, str, a);
                } else {
                    Toolkit.getDefaultToolkit().beep();
                }
            }

            public void insertString(FilterBypass fb, int offs, String str,
                    AttributeSet a) throws BadLocationException {

                String text = fb.getDocument().getText(0,
                        fb.getDocument().getLength());
                text += str;
                if ((fb.getDocument().getLength() + str.length()) <= maxCharacters
                        && text.matches("^[0-9]+[.]?[0-9]{0,1}$")) {
                    super.insertString(fb, offs, str, a);
                } else {
                    Toolkit.getDefaultToolkit().beep();
                }
            }
        });
        return field;
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new FilterDemo();
            }
        });
    }
}

这篇关于JTextField,使用文档过滤器过滤整数和句点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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