Позволяет вводить в JTextField только числа и символ (-)

#java #swing #jframe #jtextfield #documentfilter

#java #swing #jframe #jtextfield #documentfilter

Вопрос:

Я пытаюсь создать тест по математике, и я только хочу, чтобы пользователь мог вводить числа, независимо от того, являются ли они отрицательными или положительными. Есть ли какой-либо способ сделать это? Я думал об использовании регулярных выражений, но я слышал, что они плохи в использовании. Я пытался использовать keylistener, но что тогда, если пользователь вставит? Я попытался проанализировать строку, чтобы получить целое число, но тогда отрицательный символ не будет работать.

Есть идеи?

 package com.quiz.ui;

import java.awt.BorderLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class SSCCE {

    private JFrame frame;

    private JPanel contentPane;

    private JTextField usernameField;

    public static void main(String[] arguments) {
        new SSCCE().construct();
    }

    public void construct() {
        frame = new JFrame("Login");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(getContentPane());
        frame.pack();
        frame.setVisible(true);
    }

    public JPanel getContentPane() {
        usernameField = new JTextField(5);
        usernameField.addKeyListener(new KeyListener() {

            @Override
            public void keyPressed(KeyEvent arg0) {
                int keyCode = arg0.getKeyCode();
                if ((keyCode > 47 amp;amp; keyCode < 58) || keyCode == 45) {
                    arg0.consume();
                }
                System.out.println(arg0.getKeyCode());
            }

            @Override
            public void keyReleased(KeyEvent arg0) {
                // TODO Auto-generated method stub

            }

            @Override
            public void keyTyped(KeyEvent arg0) {
                // TODO Auto-generated method stub

            }
        });

        contentPane = new JPanel(new BorderLayout());
        contentPane.add(usernameField);

        return contentPane;
    }

}
  

Ответ №1:

Используйте DocumentFilter:

NumberOnlyFilter.java:

 import javax.swing.*;
import javax.swing.text.*;
import java.util.regex.*;
public 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);
    }

    /**
     * This method checks if a String contains only numbers
     */
    public boolean containsOnlyNumbers(String text)
    {
        Pattern pattern = Pattern.compile("([ -]{0,1})?[\d]*");
        Matcher matcher = pattern.matcher(text);
        boolean isMatch = matcher.matches();
        return isMatch;
    }

}
  

и затем вы можете использовать его как:

 ((AbstractDocument)yourTxtField.getDocument()).setDocumentFilter(new NumberOnlyFilter());
  

Комментарии:

1. 1 У меня всегда возникает соблазн предварительно скомпилировать шаблон, но профилированное преимущество обычно незначительно.

2. Проблема с этим заключается в том, что символ - также должен быть разрешен.

3. @Ron: Предложение Eng отличное (1 ), и вы можете легко использовать предложение Eng и разрешить, либо проанализировав строку, чтобы увидеть, является ли она подходящим числовым представлением, либо используя другую логику в фильтре.

4. adjustLabel(...) Метод не может быть найден.

5. @Ron Ой, я всегда копирую этот код из своих старых файлов и забываю удалить adjustLabel() , извините 🙂

Ответ №2:

В качестве альтернативы, рассмотрите возможность проверки ввода с помощью InputVerifier . Также может подойти форматированное текстовое поле.

Ответ №3:

Вы можете использовать Integer.parseInt(строка s, исходный код int), для десятичной системы счисления используйте 10 в качестве значения redix.

Комментарии:

1. Отрицательный символ не проходит проверку при использовании этого метода.

2. я не пробовал код, но в этой ссылке говорится, что он вернет отрицательное значение, [ссылка]( download.oracle.com/javase/1.4.2/docs/api/java/lang /… , int))