如何在javaFX 2.0中实现NumberField?

Anu*_*dha 20 user-interface input javafx-2

我需要在我的UI中插入一个数字字段.所以我需要检查文本字段上的键事件,以检查输入字符是否是数字.我通过扩展TextField创建了一个类.如果TextField类中有一个处理keyEvents的方法,我可以简单地用适合数字字段的方法覆盖该方法.有任何想法吗?

谢谢

jew*_*sea 14

2016年5月27日更新

Java 8u40引入了TextFormatter类,这是实现此功能的推荐方法(尽管此答案中提供的解决方案仍然有效).有关详细信息,请参阅Uwe的答案,Hassan的答案以及其他提及TextFormatter的答案以下问题:

从这个问题的另一个答案中我也没有尝试过这个解决方案,但看起来不错,并删除了StackOverflow主持人:

TextField numberField = new TextField();
numberField.setTextFormatter(new TextFormatter<>(new NumberStringConverter()));
Run Code Online (Sandbox Code Playgroud)

上面的代码错过了TextFormatter的UnaryOperator过滤器,你通常也需要它(否则,该字段不会显示限制用户输入只有格式化值,它只允许你通过文本格式化程序值属性监视未格式化的值).要扩展解决方案以使用过滤器,可以使用以下代码:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.scene.control.TextFormatter;
import javafx.stage.Stage;
import javafx.util.converter.NumberStringConverter;

import java.text.ParsePosition;
import java.util.function.UnaryOperator;

public class NumberConverterFieldTest extends Application {
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage) {
        TextField numberField = new TextField();
        NumberStringFilteredConverter converter = new NumberStringFilteredConverter();
        final TextFormatter<Number> formatter = new TextFormatter<>(
                converter,
                0,
                converter.getFilter()
        );

        numberField.setTextFormatter(formatter);

        formatter.valueProperty().addListener((observable, oldValue, newValue) ->
                System.out.println(newValue)
        );

        stage.setScene(new Scene(numberField));
        stage.show();
    }

    class NumberStringFilteredConverter extends NumberStringConverter {
        // Note, if needed you can add in appropriate constructors 
        // here to set locale, pattern matching or an explicit
        // type of NumberFormat.
        // 
        // For more information on format control, see 
        //    the NumberStringConverter constructors
        //    DecimalFormat class 
        //    NumberFormat static methods for examples.
        // This solution can instead extend other NumberStringConverters if needed
        //    e.g. CurrencyStringConverter or PercentageStringConverter.

        public UnaryOperator<TextFormatter.Change> getFilter() {
            return change -> {
                String newText = change.getControlNewText();
                if (newText.isEmpty()) {
                    return change;
                }

                ParsePosition parsePosition = new ParsePosition( 0 );
                Object object = getNumberFormat().parse( newText, parsePosition );
                if ( object == null || parsePosition.getIndex() < newText.length()) {
                    return null;
                } else {
                    return change;
                }
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

运行上面的示例时,编辑输入字段并按Enter键以查看更新的值(更新后的值将System.out更改).

有关教程,请参阅:


这是Urs引用的相同解决方案,但是我只是把它放在一个完全可执行的程序中,在上下文中提供一个示例并修改正则表达式(通过添加*到最后),以便复制和粘贴工作,它没有问题Uluk指的是.解决方案似乎非常简单,可能足以满足大多数目的:

import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;

public class NumericTextFieldTest extends Application {
  public static void main(String[] args) { launch(args); }

  @Override public void start(Stage stage) {
    TextField numberField = new TextField() {
      @Override public void replaceText(int start, int end, String text) {
        if (text.matches("[0-9]*")) {
          super.replaceText(start, end, text);
        }
      }

      @Override public void replaceSelection(String text) {
        if (text.matches("[0-9]*")) {
          super.replaceSelection(text);
        }
      }
    };

    stage.setScene(new Scene(numberField));
    stage.show();
  }
}
Run Code Online (Sandbox Code Playgroud)

替代解决方案

您可能还对我在JavaFX示例中的替代解决方案感兴趣,该示例将滑块值绑定到可编辑的TextField.在该解决方案中,我扩展TextField以在字段上公开IntegerProperty以用于简单绑定目的.替代解决方案类似于原始海报在更新的问题中概述的解决方案(即添加了事件过滤器以限制来自键事件的输入数据),但另外在TextField的text属性上添加了ChangeListener以确保复制和粘贴的值仅在数字时才被接受.

在JavaFX 2.0中的JavaFX论坛主题数字文本字段中还有其他一些解决方案可以解决这个问题吗?其中包括对FXExperience控件数字字段的引用.


Anu*_*dha 3

找到了解决方案。:)

public class NumFieldFX extends TextField {
   public NumFieldFX() {
      this.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
         public void handle( KeyEvent t ) {
            char ar[] = t.getCharacter().toCharArray();
            char ch = ar[t.getCharacter().toCharArray().length - 1];
            if (!(ch >= '0' && ch <= '9')) {
               System.out.println("The char you entered is not a number");
               t.consume();
            }
         }
      });
   }
}
Run Code Online (Sandbox Code Playgroud)