как текстовое поле может устанавливать только для ввода чисел в сетевых бобах? [Дубликат]

Во-первых, вам нужно иметь четкое представление о scope и поведении ключевого слова this в контексте scope.

this & amp; scope:


there are two types of scope in javascript. They are :

   1) Global Scope

   2) Function Scope

вкратце, глобальная область относится к объекту window.Variables, объявленные в глобальной области, доступны из любого места. С другой стороны, область функций находится внутри функции .variable, объявленный внутри функции, не может быть доступен из внешнего мира в обычном режиме. this ключевое слово в глобальной области относится к объекту window. Внутренняя функция this также относится к объекту window.So this всегда будет ссылаться на окно до тех пор, пока мы найдем способ манипулировать this, чтобы указать контекст по собственному выбору.

--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   ( globally "this" refers to window object)                                 -     
-                                                                              -
-         function outer_function(callback){                                   -
-                                                                              -
-               // outer function scope                                        -
-               // inside outer function"this" keyword refers to window object -                                                                              -
-              callback() // "this" inside callback also refers window object  -

-         }                                                                    -
-                                                                              -
-         function callback_function(){                                        -
-                                                                              -
-                //  function to be passed as callback                         -
-                                                                              -
-                // here "THIS" refers to window object also                   -
-                                                                              -
-         }                                                                    -
-                                                                              -
-         outer_function(callback_function)                                    -
-         // invoke with callback                                              -
--------------------------------------------------------------------------------

Различные способы управления this внутри функций обратного вызова:

Здесь У меня есть функция-конструктор, называемая Person. Он имеет свойство, называемое name, и четыре метода, называемые sayNameVersion1, sayNameVersion2, sayNameVersion3, sayNameVersion4. Все четыре из них имеют одну конкретную задачу. Заберите обратный вызов и вызовите его. Обратный вызов имеет конкретную задачу, которая заключается в регистрации свойства имени экземпляра функции конструктора Person.

function Person(name){

    this.name = name

    this.sayNameVersion1 = function(callback){
        callback.bind(this)()
    }
    this.sayNameVersion2 = function(callback){
        callback()
    }

    this.sayNameVersion3 = function(callback){
        callback.call(this)
    }

    this.sayNameVersion4 = function(callback){
        callback.apply(this)
    }

}

function niceCallback(){

    // function to be used as callback

    var parentObject = this

    console.log(parentObject)

}

Теперь давайте создадим экземпляр из конструктора person и вызывать разные версии sayNameVersionX (X относится к 1,2,3,4) методу с niceCallback, чтобы увидеть, как много способов управления this внутри обратного вызова ссылаться на person.

var p1 = new Person('zami') // create an instance of Person constructor

bind:

Что нужно сделать, это создать новую функцию с ключевым словом this, установленным на предоставленное значение.

sayNameVersion1 и sayNameVersion2 используют bind для управления this функции обратного вызова.

this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}

сначала связывают this с обратным вызовом внутри самого метода. для второго обратного вызова передается связанный с ним объект.

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

вызов:

first argument в call используется как функция this внутри функции, которая вызывается с call, прикрепленной к ней.

sayNameVersion3 использует call для управления this ], чтобы ссылаться на созданный нами объект person, а не на объект окна.

this.sayNameVersion3 = function(callback){
    callback.call(this)
}

и он называется следующим:

p1.sayNameVersion3(niceCallback)

apply:

Как и в call, первый аргумент apply относится к объекту, который будет обозначен ключевым словом this.

sayNameVersion4 использует apply для манипулирования this для обращения к объекту человека

this.sayNameVersion4 = function(callback){
    callback.apply(this)
}

, и он называется следующим. Просто передается обратный вызов,

p1.sayNameVersion4(niceCallback)

39
задан Lukas Rotter 14 December 2015 в 18:02
поделиться

19 ответов

Простой подход заключается в подклассе JTextField и переопределении createDefaultModel () путем возврата настраиваемого подкласса PlainDocument. Пример - текстовое поле только для целых чисел:

public class NumberField extends JTextField {


@Override
protected Document createDefaultModel() {
    return new Numberdocument();
}

class Numberdocument extends PlainDocument
{
    String numbers="1234567890-";
    @Override
    public void insertString(int offs, String str, AttributeSet a)
            throws BadLocationException {
        if(!numbers.contains(str));
        else    super.insertString(offs, str, a);
    }
}

Способ ввода в insertString () любым способом.

4
ответ дан Alexiy 21 August 2018 в 16:49
поделиться
  • 1
    Thx, но, возможно, лучше писать if (numbers.contains (str) {super.insertString} – Lawrence 31 January 2016 в 19:20
  • 2
    @Lawrence Да, иногда я пропускаю логику. – Alexiy 10 August 2016 в 09:04
DataTF.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent eve) {
                String AllowedData="0123456789.";
                char enter = eve.getKeyChar();
                if (!AllowedData.contains(String.valueOf(enter))) {
                    eve.consume();
                }
            }       
        });  
0
ответ дан Ali Mostafa 21 August 2018 в 16:49
поделиться

Хотя есть чистое зло JFormattedTextField, нет тривиального способа сделать это, используя только библиотеку Swing.

Некоторый код, который я подготовил ранее. Немного описания.

7
ответ дан banjollity 21 August 2018 в 16:49
поделиться

Быстрое решение:

JTextField textField = new JTextField() {
  public void processKeyEvent(KeyEvent ev) {
    char c = ev.getKeyChar();
    if (c >= 48 && c <= 57) { // c = '0' ... c = '9'
      super.processKeyEvent(ev);
    }
  }
};

Проблема с вышеупомянутым решением заключается в том, что пользователь не может использовать клавиши «Удалить», «Стрелка влево», «Стрелка вправо» или «Назад» в текстовом поле, поэтому я предлагаю использовать это решение:

this.portTextField = new JTextField() {
  public void processKeyEvent(KeyEvent ev) {
    char c = ev.getKeyChar();
    try {
      // Ignore all non-printable characters. Just check the printable ones.
      if (c > 31 && c < 127) {
        Integer.parseInt(c + "");
      }
      super.processKeyEvent(ev);
    }
    catch (NumberFormatException nfe) {
      // Do nothing. Character inputted is not a number, so ignore it.
    }
  }
};
3
ответ дан BJ Peter DeLaCruz 21 August 2018 в 16:49
поделиться
  • 1
    Будьте осторожны: не все символы с KeyValue & gt; 127 являются непечатаемыми символами. то есть «§» или «ß» все еще можно ввести во второй фрагмент кода. Просто замените 127 на 65535 и проверьте, не имеет ли значение 127 (клавиша удаления), чтобы работать там (т. Е. KeyArrows получил здесь значение 65535). если (c & gt; 31 & amp; c & lt; 65535 & amp; c! = 127) – Constantin 8 March 2013 в 15:34
  • 2
    -1 из-за сломанного решения. Это только фильтрует такие вещи, как ввод в «5». Вы можете копировать / вставлять в & quot; asdf & quot; без его фильтрации. – Alex Meiburg 17 March 2013 в 08:15
  • 3
    @BJ Peter DeLaCruz Спасибо за это решение, он отлично работал для меня, сэкономил много времени. Спасибо :) – Luffy 4 May 2015 в 12:17
  • 4
    (1), Не играйте с KeyEvents. Swing имеет более новые и лучшие API (такие как DocumentFilter), которые будут работать во всех ситуациях. Это решение не будет работать, если вы «вставляете». текст в текстовое поле. – camickr 19 September 2015 в 14:48

Очень простое решение - использовать прослушиватель действий.

TextFieldActionPerformed(java.awt.event.ActionEvent evt) {

  try{

    Integer.parseInteger(TextField.getText());

  }
  catch(Exception e){

    JOptionPane.showMessageDialog(null, "Please insert Valid Number Only");

    TextField.setText(TextField.getText().substring(0,TextField.getText().length()-1));
  }

}

Вы можете использовать его и для Double:

Double.parseDouble(TextField.getText());
0
ответ дан BSMP 21 August 2018 в 16:49
поделиться

Этот вопрос был назван «точным дубликатом» другого вопроса, который с тех пор был закрыт. Ответы на этот вопрос были настолько бедными, что я был вдохновлен помочь кому-либо, кто мог бы найти его позже, путем ссылки на гораздо лучший ответ для этого случая использования.

Это ответ на закрытый вопрос & amp; могут быть суммированы как ..

Вместо этого используйте JSpinner.

9
ответ дан Community 21 August 2018 в 16:49
поделиться

Попробуйте это в событии с нажатой клавишей для связанного JTextField.

private void JTextField(java.awt.event.KeyEvent evt) {

    // TODO add your handling code here:
    char enter = evt.getKeyChar();
    if(!(Character.isDigit(enter))){
        evt.consume();
    }
}
0
ответ дан Erangad 21 August 2018 в 16:49
поделиться

записать этот код в введенный ключ

char c=evt.getKeyChar();
if(!(Character.isDigit(c) || (c==KeyEvent.VK_BACK_SPACE || c==KeyEvent.VK_DELETE)))
{
    getToolkit().beep();
    evt.consume();
}
0
ответ дан Mohammad Ashfaq 21 August 2018 в 16:49
поделиться
  • 1
    (1-), Не играйте с ключевыми событиями. Swing имеет более новые и лучшие API (такие как DocumentFilter), которые будут работать во всех ситуациях. Это решение не будет работать, если вы «вставляете». текст в текстовое поле. – camickr 19 September 2015 в 14:52

Вы хотели бы взглянуть на JFormattedTextField

Форматированные текстовые поля предоставляют разработчикам возможность указать допустимый набор символов, которые могут быть напечатано в текстовом поле

Это подкласс JTextField, поэтому вы можете использовать его следующим образом:

JTextField textField = new JFormattedTextField(NumberFormat.getInstance());
-1
ответ дан OscarRyz 21 August 2018 в 16:49
поделиться
if (JTextField.getText().equals("") || !(Pattern.matches("^[0-9]+$", JTextField.getText()))) {
     JOptionPane.showMessageDialog(null, " JTextField Invalide !!!!! ");
   }
  • , если JTextField.getText (). equals ("") == -> если JTextField пуст
  • , если (! (Pattern.matches ("^ [0-9 ] + $ ", JTextField.getText ()))) == -> если TextField содержит другие символы, чем те
  • JOptionPane.showMessageDialog (null," JTextField Invalide !!!!! "); == ->, поэтому это сообщение будет отличаться
1
ответ дан Rbj93 21 August 2018 в 16:49
поделиться
  • 1
    Это может быть ответ, но добавьте адекватное описание для его поддержки. – Ani Menon 14 May 2016 в 16:25
import javax.swing.*;
import javax.swing.text.*;

public class JNumberTextField extends JTextField
{
    private static final char DOT = '.';
    private static final char NEGATIVE = '-';
    private static final String BLANK = "";
    private static final int DEF_PRECISION = 2;

    public static final int NUMERIC = 2;
    public static final int DECIMAL = 3;

    public static final String FM_NUMERIC = "0123456789";
    public static final String FM_DECIMAL = FM_NUMERIC + DOT;

    private int maxLength = 0;
    private int format = NUMERIC;
    private String negativeChars = BLANK;
    private String allowedChars = null;
    private boolean allowNegative = false;
    private int precision = 0;

    protected PlainDocument numberFieldFilter;

    public JNumberTextField()
    {
        this( 10, NUMERIC );
    }

    public JNumberTextField( int maxLen )
    {
        this( maxLen, NUMERIC );
    }

    public JNumberTextField( int maxLen, int format )
    {
        setAllowNegative( true );
        setMaxLength( maxLen );
        setFormat( format );

        numberFieldFilter = new JNumberFieldFilter();
        super.setDocument( numberFieldFilter );
    }

    public void setMaxLength( int maxLen )
    {
        if (maxLen > 0)
            maxLength = maxLen;
        else
            maxLength = 0;
    }

    public int getMaxLength()
    {
        return maxLength;
    }

    public void setPrecision( int precision )
    {
        if ( format == NUMERIC )
            return;

        if ( precision >= 0 )
            this.precision = precision;
        else
            this.precision = DEF_PRECISION;
    }

    public int getPrecision()
    {
        return precision;
    }

    public Number getNumber()
    {
        Number number = null;

        if ( format == NUMERIC )
            number = new Integer(getText());
        else
            number = new Double(getText());

        return number;
    }

    public void setNumber( Number value )
    {
        setText(String.valueOf(value));
    }

    public int getInt()
    {
        return Integer.parseInt( getText() );
    }

    public void setInt( int value )
    {
        setText( String.valueOf( value ) );
    }

    public float getFloat()
    {
        return ( new Float( getText() ) ).floatValue();
    }

    public void setFloat(float value)
    {
        setText( String.valueOf( value ) );
    }

    public double getDouble()
    {
        return ( new Double( getText() ) ).doubleValue();
    }

    public void setDouble(double value)
    {
        setText( String.valueOf(value) );
    }

    public int getFormat()
    {
        return format;
    }

    public void setFormat(int format)
    {
        switch ( format )
        {
        case NUMERIC:
        default:
            this.format = NUMERIC;
            this.precision = 0;
            this.allowedChars = FM_NUMERIC;
            break;

        case DECIMAL:
            this.format = DECIMAL;
            this.precision = DEF_PRECISION;
            this.allowedChars = FM_DECIMAL;
            break;
        }
    }

    public void setAllowNegative( boolean value )
    {
        allowNegative = value;

        if ( value )
            negativeChars = "" + NEGATIVE;
        else
            negativeChars = BLANK;
    }

    public boolean isAllowNegative()
    {
        return allowNegative;
    }

    public void setDocument( Document document )
    {
    }

    class JNumberFieldFilter extends PlainDocument
    {
        public JNumberFieldFilter()
        {
            super();
        }

        public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException
        {
            String text = getText(0,offset) + str + getText(offset,(getLength() - offset));

            if ( str == null || text == null )
                return;

            for ( int i=0; i<str.length(); i++ )
            {
                if ( ( allowedChars + negativeChars ).indexOf( str.charAt(i) ) == -1)
                    return;
            }

            int precisionLength = 0, dotLength = 0, minusLength = 0;
            int textLength = text.length();

            try
            {
                if ( format == NUMERIC )
                {
                    if ( ! ( ( text.equals( negativeChars ) ) && ( text.length() == 1) ) )
                        new Long(text);
                }
                else if ( format == DECIMAL )
                {
                    if ( ! ( ( text.equals( negativeChars ) ) && ( text.length() == 1) ) )
                        new Double(text);

                    int dotIndex = text.indexOf(DOT);
                    if( dotIndex != -1 )
                    {
                        dotLength = 1;
                        precisionLength = textLength - dotIndex - dotLength;

                        if( precisionLength > precision )
                            return;
                    }
                }
            }
            catch(Exception ex)
            {
                return;
            }

            if ( text.startsWith( "" + NEGATIVE ) )
            {
                if ( !allowNegative )
                    return;
                else
                    minusLength = 1;
            }

            if ( maxLength < ( textLength - dotLength - precisionLength - minusLength ) )
                return;

            super.insertString( offset, str, attr );
        }
    }
}
8
ответ дан Rin 21 August 2018 в 16:49
поделиться

Поскольку этот вопрос повторяется довольно часто, я прилагаю к этому больше усилий, чем обычно.

Мое голосование идет к JFormattedTextField. ИМО каждый разработчик Swing должен иметь улучшенную версию этого класса в своем наборе инструментов, поскольку он позволяет проверять почти все, что вы можете себе представить, правильным выбором Format. Примеры, для которых я уже использовал его:

  • Ввод строки, где String не может быть пустым
  • Вход координат
  • Дата ввода
  • Редактор на JSpinner
  • Масштаб карты
  • Номера
  • ...

Это также позволяет визуальную обратную связь, когда вход недействителен, например, не в случае с InputVerifier. Он по-прежнему позволяет пользователю вводить что-либо, но это значение просто не принимается, когда оно недействительно, и это значение никогда не покидает пользовательский интерфейс. Я думаю (но опять же, это мое мнение), что лучше разрешить пользователю вводить недопустимый ввод, который просто удаляет это автоматически, например. a DocumentFilter. Я бы заподозрил ошибку при типе символа в текстовом поле, и он не появляется.

Позвольте мне проиллюстрировать это с помощью некоторого кода (на самом деле, кода). Сначала небольшое демо-приложение. Это приложение просто показывает номер JFormattedTextField для чисел. Просто использование другого формата позволяет повторно использовать этот компонент для совершенно разных валидаций.

enter image description here [/g0]

import be.pcl.swing.ImprovedFormattedTextField;

import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.NumberFormat;

/**
 * See http://stackoverflow.com/q/1313390/1076463
 */
public class FormattedTextFieldDemo {
  public static void main( String[] args ) {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        JFrame testFrame = new JFrame( "FormattedTextFieldDemo" );

        NumberFormat integerNumberInstance = NumberFormat.getIntegerInstance();
        ImprovedFormattedTextField integerFormattedTextField = new ImprovedFormattedTextField( integerNumberInstance, 100 );
        integerFormattedTextField.setColumns( 20 );

        testFrame.add( createButtonPanel( integerFormattedTextField ), BorderLayout.NORTH );

        final JTextArea textArea = new JTextArea(50, 50);
        PropertyChangeListener updateTextAreaListener = new PropertyChangeListener() {
          @Override
          public void propertyChange( PropertyChangeEvent evt ) {
            textArea.append( "New value: " + evt.getNewValue() + "\n" );
          }
        };
        integerFormattedTextField.addPropertyChangeListener( "value", updateTextAreaListener );

        testFrame.add( new JScrollPane( textArea ), BorderLayout.CENTER );

        testFrame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
        testFrame.pack();
        testFrame.setVisible( true );
      }
    } );

  }

  private static JPanel createButtonPanel( final JFormattedTextField aTextField ){
    JPanel panel = new JPanel( new BorderLayout(  ) );
    panel.add( aTextField, BorderLayout.WEST );

    Action action = new AbstractAction() {
      {
        aTextField.addPropertyChangeListener( "editValid", new PropertyChangeListener() {
          @Override
          public void propertyChange( PropertyChangeEvent evt ) {
            setEnabled( ( ( Boolean ) evt.getNewValue() ) );
          }
        } );
        putValue( Action.NAME, "Show current value" );
      }
      @Override
      public void actionPerformed( ActionEvent e ) {
        JOptionPane.showMessageDialog( null, "The current value is [" + aTextField.getValue() + "] of class [" + aTextField.getValue().getClass() + "]" );
      }
    };
    panel.add( new JButton( action ), BorderLayout.EAST );
    return panel;
  }
}

, который показывает только ImprovedFormattedTextField и JButton который активируется только тогда, когда вход действителен (ага, есть это решение DocumentFilter). Он также показывает JTextArea, в котором значение печатается каждый раз, когда встречается новое действительное значение. Нажатие кнопки показывает значение.

Код для ImprovedFormattedTextField можно найти ниже, вместе с ParseAllFormat, на котором он зависит

package be.pcl.swing;

import javax.swing.JFormattedTextField;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.Color;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.text.Format;
import java.text.ParseException;

/**
 * <p>Extension of {@code JFormattedTextField} which solves some of the usability issues</p>
 */
public class ImprovedFormattedTextField extends JFormattedTextField {

  private static final Color ERROR_BACKGROUND_COLOR = new Color( 255, 215, 215 );
  private static final Color ERROR_FOREGROUND_COLOR = null;

  private Color fBackground, fForeground;

  /**
   * Create a new {@code ImprovedFormattedTextField} instance which will use {@code aFormat} for the
   * validation of the user input.
   *
   * @param aFormat The format. May not be {@code null}
   */
  public ImprovedFormattedTextField( Format aFormat ) {
    //use a ParseAllFormat as we do not want to accept user input which is partially valid
    super( new ParseAllFormat( aFormat ) );
    setFocusLostBehavior( JFormattedTextField.COMMIT_OR_REVERT );
    updateBackgroundOnEachUpdate();
    //improve the caret behavior
    //see also http://tips4java.wordpress.com/2010/02/21/formatted-text-field-tips/
    addFocusListener( new MousePositionCorrectorListener() );
  }

  /**
   * Create a new {@code ImprovedFormattedTextField} instance which will use {@code aFormat} for the
   * validation of the user input. The field will be initialized with {@code aValue}.
   *
   * @param aFormat The format. May not be {@code null}
   * @param aValue  The initial value
   */
  public ImprovedFormattedTextField( Format aFormat, Object aValue ) {
    this( aFormat );
    setValue( aValue );
  }

  private void updateBackgroundOnEachUpdate() {
    getDocument().addDocumentListener( new DocumentListener() {
      @Override
      public void insertUpdate( DocumentEvent e ) {
        updateBackground();
      }

      @Override
      public void removeUpdate( DocumentEvent e ) {
        updateBackground();
      }

      @Override
      public void changedUpdate( DocumentEvent e ) {
        updateBackground();
      }
    } );
  }

  /**
   * Update the background color depending on the valid state of the current input. This provides
   * visual feedback to the user
   */
  private void updateBackground() {
    boolean valid = validContent();
    if ( ERROR_BACKGROUND_COLOR != null ) {
      setBackground( valid ? fBackground : ERROR_BACKGROUND_COLOR );
    }
    if ( ERROR_FOREGROUND_COLOR != null ) {
      setForeground( valid ? fForeground : ERROR_FOREGROUND_COLOR );
    }
  }

  @Override
  public void updateUI() {
    super.updateUI();
    fBackground = getBackground();
    fForeground = getForeground();
  }

  private boolean validContent() {
    AbstractFormatter formatter = getFormatter();
    if ( formatter != null ) {
      try {
        formatter.stringToValue( getText() );
        return true;
      } catch ( ParseException e ) {
        return false;
      }
    }
    return true;
  }

  @Override
  public void setValue( Object value ) {
    boolean validValue = true;
    //before setting the value, parse it by using the format
    try {
      AbstractFormatter formatter = getFormatter();
      if ( formatter != null ) {
        formatter.valueToString( value );
      }
    } catch ( ParseException e ) {
      validValue = false;
      updateBackground();
    }
    //only set the value when valid
    if ( validValue ) {
      int old_caret_position = getCaretPosition();
      super.setValue( value );
      setCaretPosition( Math.min( old_caret_position, getText().length() ) );
    }
  }

  @Override
  protected boolean processKeyBinding( KeyStroke ks, KeyEvent e, int condition, boolean pressed ) {
    //do not let the formatted text field consume the enters. This allows to trigger an OK button by
    //pressing enter from within the formatted text field
    if ( validContent() ) {
      return super.processKeyBinding( ks, e,
                                      condition, pressed ) && ks != KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 );
    }
    else {
      return super.processKeyBinding( ks, e,
                                      condition, pressed );
    }
  }

  private static class MousePositionCorrectorListener extends FocusAdapter {
    @Override
    public void focusGained( FocusEvent e ) {
      /* After a formatted text field gains focus, it replaces its text with its
       * current value, formatted appropriately of course. It does this after
       * any focus listeners are notified. We want to make sure that the caret
       * is placed in the correct position rather than the dumb default that is
        * before the 1st character ! */
      final JTextField field = ( JTextField ) e.getSource();
      final int dot = field.getCaret().getDot();
      final int mark = field.getCaret().getMark();
      if ( field.isEnabled() && field.isEditable() ) {
        SwingUtilities.invokeLater( new Runnable() {
          @Override
          public void run() {
            // Only set the caret if the textfield hasn't got a selection on it
            if ( dot == mark ) {
              field.getCaret().setDot( dot );
            }
          }
        } );
      }
    }
  }
}

. ParseAllFormat class:

package be.pcl.swing;

import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;

/**
 * <p>Decorator for a {@link Format Format} which only accepts values which can be completely parsed
 * by the delegate format. If the value can only be partially parsed, the decorator will refuse to
 * parse the value.</p>
 */
public class ParseAllFormat extends Format {
  private final Format fDelegate;

  /**
   * Decorate <code>aDelegate</code> to make sure if parser everything or nothing
   *
   * @param aDelegate The delegate format
   */
  public ParseAllFormat( Format aDelegate ) {
    fDelegate = aDelegate;
  }

  @Override
  public StringBuffer format( Object obj, StringBuffer toAppendTo, FieldPosition pos ) {
    return fDelegate.format( obj, toAppendTo, pos );
  }

  @Override
  public AttributedCharacterIterator formatToCharacterIterator( Object obj ) {
    return fDelegate.formatToCharacterIterator( obj );
  }

  @Override
  public Object parseObject( String source, ParsePosition pos ) {
    int initialIndex = pos.getIndex();
    Object result = fDelegate.parseObject( source, pos );
    if ( result != null && pos.getIndex() < source.length() ) {
      int errorIndex = pos.getIndex();
      pos.setIndex( initialIndex );
      pos.setErrorIndex( errorIndex );
      return null;
    }
    return result;
  }

  @Override
  public Object parseObject( String source ) throws ParseException {
    //no need to delegate the call, super will call the parseObject( source, pos ) method
    return super.parseObject( source );
  }
}

Возможные улучшения:

  • setBackground не соблюдается всеми Look-and-Feels. Иногда вы можете использовать setForeground вместо этого, но даже это не гарантируется всеми L & amp; Fs. Поэтому для визуальной обратной связи может быть лучше использовать восклицательный знак, расположенный рядом с полем. Недостатком является то, что это может испортить макет, если вы вдруг добавите / удалите значок
  • , обратная связь указывает только на то, что вход действителен / недействителен. Нет ничего, что указывало бы на ожидаемый формат. Возможным решением является использование самоподготовленного расширения Format, которое включает описание / пример допустимого ввода, и поместите его в качестве подсказки на JFormattedTextField.
53
ответ дан Robin 21 August 2018 в 16:49
поделиться
  • 1
    Отличный ответ. +1 – Andrew Thompson 17 November 2012 в 08:04
  • 2
    @AndrewThompson Мне нужен был один. Поскольку этот вопрос возникает часто, мне нужен был ответ, на который я мог бы ссылаться в будущем. И поскольку этот вопрос уже получил + 10 тыс. Просмотров, казалось, подходящее место для добавления такого ответа – Robin 17 November 2012 в 11:23
  • 3
    Это лучший ответ, который я нашел где угодно. Благодарю. – Jeff Walker 20 May 2013 в 16:42
  • 4
    Можно ли JFormattedTextField использовать только алфавиты переменной длины? – Akshat 1 April 2015 в 16:06
  • 5
    @ В любом случае вы можете использовать форматированное текстовое поле в сочетании с любой реализацией java.util.format, о которой вы можете думать – Robin 1 April 2015 в 16:39

Вы можете создать красивое текстовое поле в java, которое принимает или разрешает только числовые значения. Вы даже можете установить точность для значений float ... проверьте код в zybocodes

-2
ответ дан sid 21 August 2018 в 16:49
поделиться
  • 1
    Заявляя, что вопрос имеет «прекрасный ответ», не является, по сути, хорошим ответом. Ссылка на код не так хороша, как добавление фрагмента кода или, по крайней мере, объяснение того, как оно отличается от других ответов. – tucuxi 4 April 2016 в 09:31

numberField = new JFormattedTextField (NumberFormat.getInstance ());

Учебник по форматированному текстовому полю

-1
ответ дан Stefan Kendall 21 August 2018 в 16:49
поделиться
  • 1
    Это то, о чем я думал, прежде чем я потерпел неудачу, и поэтому искал здесь решение. К сожалению, JFormattedTextField проверяет ввод только при выходе из поля, а не во время редактирования, поэтому можно ввести недопустимое значение. Если вход должен быть отслежен, то уже слишком поздно. – mh. 29 April 2011 в 16:12

Я думаю, что это лучшее решение:

JTextField textField = new JFormattedTextField(new MaskFormatter("###")); //
-1
ответ дан sth 21 August 2018 в 16:49
поделиться

Рассматривая количество просмотров, которые этот вопрос получает, я не нашел ни одного из вышеупомянутых решений, подходящих для моей проблемы. Я решил создать пользовательский PlainDocument , чтобы он соответствовал моим потребностям. Это решение также подает звуковой сигнал при достижении максимального количества символов, или вставленный текст не является целым числом.

private class FixedSizeNumberDocument extends PlainDocument
{
    private JTextComponent owner;
    private int fixedSize;

    public FixedSizeNumberDocument(JTextComponent owner, int fixedSize)
    {
        this.owner = owner;
        this.fixedSize = fixedSize;
    }

    @Override
    public void insertString(int offs, String str, AttributeSet a)
            throws BadLocationException
    {
        if (getLength() + str.length() > fixedSize) {
            str = str.substring(0, fixedSize - getLength());
            this.owner.getToolkit().beep();
        }

        try {
            Integer.parseInt(str);
        } catch (NumberFormatException e) {
            // inserted text is not a number
            this.owner.getToolkit().beep();
            return;
        }

        super.insertString(offs, str, a);
    }               
}

имплантируется следующим образом:

    JTextField textfield = new JTextField();
    textfield.setDocument(new FixedSizeNumberDocument(textfield,5));
2
ответ дан Terraego 21 August 2018 в 16:49
поделиться

Также рассмотрите использование InputVerifier .

2
ответ дан trashgod 21 August 2018 в 16:49
поделиться

Используйте formatter для форматирования текстового поля.

NumberFormat format = NumberFormat.getInstance();
format.setGroupingUsed(false);
NumberFormatter formatter = new NumberFormatter(format);
formatter.setValueClass(Integer.class);
formatter.setMaximum(65535);
formatter.setAllowsInvalid(false);
formatter.setCommitsOnValidEdit(true);
myTextField = new JFormattedTextField(formatter);
1
ответ дан XurajB 21 August 2018 в 16:49
поделиться

Посмотрите на JFormattedTextField .

0
ответ дан Zed 21 August 2018 в 16:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: