jtextfield,使用文档过滤器过滤整数和句点

t2a7ltrp  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(306)

编辑-在帖子的最后添加了我们能够得到的答案
这是我在so的第一篇帖子,所以我希望我能问得对!
我搜索了一下,并没有找到我的问题的答案,尽管类似的问题被张贴,所以我希望这不是一个转载。
这就是我得到的,一个使用 JTextField 接收用户的输入,除此之外,我还有一个 DocumentFilter 因此,用户只能输入整数和一个句点,以便接收表示权重的值。
我的问题是 DocumentFilter 我无法筛选“复制粘贴”文本,也无法筛选选定的文本。
这是过滤器的代码

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方法,所以我省略了它,但是在应用程序中实现了它。
提前感谢您的时间!
编辑-加上它现在有一个过滤器来限制高度输入太多

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();
        }
    }
}
eqqqjvef

eqqqjvef1#

这是paulsamsotha的答案的一个版本,修复了一些bug,正则表达式作为参数传递,以便更通用地使用。最初允许在输入的开头插入或替换无效字符,或删除导致字段无效的前导字符(它没有实现) remove() . 一旦出现无效字符,输入就会被锁定。
这个版本应该解决所有这些问题。
示例用法:

// Store the labels and textfields for later retrieval
  Vector<JLabel> jLabels = new Vector<JLabel>(8);
  Vector<JTextField> jTextFields = new Vector<JTextField>(8);

  //Create and populate the panel.
  Container contentPane = getContentPane();

  // Wrap everything in a BorderLayout
  JPanel borderPanel = new JPanel(new BorderLayout());
  contentPane.add(borderPanel);

  // Put the input fields in the CENTER position
  JPanel fieldPanel = new JPanel(new SpringLayout());
  borderPanel.add(fieldPanel, BorderLayout.CENTER);

  // Put the input fields in the CENTER position
  JPanel fieldPanel = new JPanel(new SpringLayout());
  borderPanel.add(fieldPanel, BorderLayout.CENTER);

  String[] labels = {"Player Name: ", "Initial Chips: "};
  String[] filters = {"^[A-Za-z][A-Za-z0-9_ ]*$", "^[1-9][0-9]*$"};
  final int numPairs = labels.length;

  // Create and associate the field inputs and labels and regex filters
  for (int i = 0; i < numPairs; i++) {
     JLabel label = new JLabel(labels[i], JLabel.TRAILING);
     fieldPanel.add(label);
     JTextField textField = createFilteredField(filters[i]);
     label.setLabelFor(textField);
     fieldPanel.add(textField);
     jLabels.add(label);
     jTextFields.add(textField);
  }

代码:

/* Filtered Text Field
 * @param   regex
 *          the regular expression to which this string is to be matched
 *
 * @return  {@code true} if, and only if, this string matches the
 *          given regular expression
 *
 * @throws  PatternSyntaxException
 *          if the regular expression's syntax is invalid
 */
public JTextField createFilteredField(String regex) {
   JTextField field = new JTextField(12);
   AbstractDocument document = (AbstractDocument) field.getDocument();
   final int maxCharacters = 20;
   document.setDocumentFilter(new DocumentFilter() {

      /**
       * Invoked prior to removal of the specified region in the
       * specified Document. Subclasses that want to conditionally allow
       * removal should override this and only call supers implementation as
       * necessary, or call directly into the <code>FilterBypass</code> as
       * necessary.
       *
       * @param fb FilterBypass that can be used to mutate Document
       * @param offset the offset from the beginning &gt;= 0
       * @param length the number of characters to remove &gt;= 0
       * @exception BadLocationException  some portion of the removal range
       *   was not a valid part of the document.  The location in the exception
       *   is the first bad position encountered.
       */
      public void remove(FilterBypass fb, int offset, int length) throws
            BadLocationException {
         String text = fb.getDocument().getText(0, fb.getDocument().getLength());
         String newText = text.substring(0, offset) + text.substring(offset + length);
         if (newText.matches(regex) || newText.length() == 0) {
            super.remove(fb, offset, length);
         }
      }

      /**
       * Invoked prior to replacing a region of text in the
       * specified Document. Subclasses that want to conditionally allow
       * replace should override this and only call supers implementation as
       * necessary, or call directly into the FilterBypass.
       *
       * @param fb FilterBypass that can be used to mutate Document
       * @param offset Location in Document
       * @param length Length of text to delete
       * @param _text Text to insert, null indicates no text to insert
       * @param attrs AttributeSet indicating attributes of inserted text,
       *              null is legal.
       * @exception BadLocationException  the given insert position is not a
       *   valid position within the document
       */
      public void replace(FilterBypass fb, int offset, int length,
                          String _text, AttributeSet attrs) throws BadLocationException {

         String text = fb.getDocument().getText(0, fb.getDocument().getLength());
         String newText = text.substring(0, offset) + _text + text.substring(offset + length);
         if (newText.length() <= maxCharacters && newText.matches(regex)) {
            super.replace(fb, offset, length, _text, attrs);
         } else {
            Toolkit.getDefaultToolkit().beep();
         }
      }

      /**
       * Invoked prior to insertion of text into the
       * specified Document. Subclasses that want to conditionally allow
       * insertion should override this and only call supers implementation as
       * necessary, or call directly into the FilterBypass.
       *
       * @param fb FilterBypass that can be used to mutate Document
       * @param offset  the offset into the document to insert the content &gt;= 0.
       *    All positions that track change at or after the given location
       *    will move.
       * @param string the string to insert
       * @param attr      the attributes to associate with the inserted
       *   content.  This may be null if there are no attributes.
       * @exception BadLocationException  the given insert position is not a
       *   valid position within the document
       */
      public void insertString(FilterBypass fb, int offset, String string,
                               AttributeSet attr) throws BadLocationException {

         String text = fb.getDocument().getText(0, fb.getDocument().getLength());
         String newText = text.substring(0, offset) + string + text.substring(offset);
         if ((fb.getDocument().getLength() + string.length()) <= maxCharacters
               && newText.matches(regex)) {
            super.insertString(fb, offset, string, attr);
         } else {
            Toolkit.getDefaultToolkit().beep();
         }
      }
   });
   return field;
}
3vpjnl9f

3vpjnl9f2#

你让过滤变得更复杂了。对于插入(如果代码相同,则为replace),您可能由于 \\. 检查。您只能粘贴一个句点,因为这是您要检查的内容。至于删除,以下建议将适用。
为了简化操作,您应该只获取文档的整个文本,然后使用regex检查整个文档字符串是否与regex匹配。这比你想做的要简单得多。你可以在这里得到一个很好的过滤过程的解释。
下面是一个示例,只使用insertstring和replace。对于remove,没有什么不同,只要获取文本,并检查它是否匹配regex。我从上面链接中的答案中选取了部分示例。场景是op需要max个字符,并且只允许一个小数位。这就是正则表达式所匹配的。但也可以匹配任何您正在键入或插入的内容,例如 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();
        }
    });
}

}

相关问题