Java 使用文本字段编辑货币

Java 使用文本字段编辑货币,java,javafx,binding,currency,Java,Javafx,Binding,Currency,如何获取JavaFX文本字段来编辑存储在没有派系数字(例如long)的货币?使用数据绑定、TextFormatter和其他javaFX工具 目标应该是: 具有LongProperty的Bo(货币价值单位:美分) 用户已知格式的可编辑文本字段(可选前导减号, 千位分隔符、十进制分隔符(货币符号),无其他 (可能的话) Bo和文本字段之间的双向绑定 这里有一个解决方案(可能不是最好的,如果我可以改进,请评论) Bo: import java.util.Random; import javafx.

如何获取JavaFX文本字段来编辑存储在没有派系数字(例如long)的货币?使用数据绑定、TextFormatter和其他javaFX工具

目标应该是:

  • 具有LongProperty的Bo(货币价值单位:美分)
  • 用户已知格式的可编辑文本字段(可选前导减号, 千位分隔符、十进制分隔符(货币符号),无其他 (可能的话)
  • Bo和文本字段之间的双向绑定
    • 这里有一个解决方案(可能不是最好的,如果我可以改进,请评论)

      Bo:

      import java.util.Random;
      
      import javafx.beans.property.LongProperty;
      import javafx.beans.property.SimpleLongProperty;
      
      public class SimpleBo {
              //a simple LongProperty to store the currency without fractional digits (56,81 € would be 5681)
              private LongProperty currencyLong = new SimpleLongProperty();
              public SimpleBo() {
                  setCurrencyLong(new Random().nextLong());
              }
              public final LongProperty currencyLongProperty() {
                  return this.currencyLong;
              }
              public final long getCurrencyLong() {
                  return this.currencyLongProperty().get();
              }
              public final void setCurrencyLong(final long currencyLong) {
                  this.currencyLongProperty().set(currencyLong);
              }
      }
      
      数字到字符串转换器:

      import java.text.NumberFormat;
      import java.util.Locale;
      
      import javafx.util.converter.NumberStringConverter;
      
      public class MyNumberStringConverter extends NumberStringConverter {
          public MyNumberStringConverter() {
              super();
          }
      
          public MyNumberStringConverter(Locale locale, String pattern) {
              super(locale, pattern);
          }
      
          public MyNumberStringConverter(Locale locale) {
              super(locale);
          }
      
          public MyNumberStringConverter(NumberFormat numberFormat) {
              super(numberFormat);
          }
      
          public MyNumberStringConverter(String pattern) {
              super(pattern);
          }
      
          @Override
          public Number fromString(String value) {
              //to transform the double, given by the textfield, just multiply by 100 and round if any left
              Number rValue = Math.round(super.fromString(value).doubleValue() * 100);
              return rValue.longValue();
          }
      
          @Override
          public String toString(Number value) {
              if(value == null) {
                  return "";
              }
              //Check for too big long value
              //If the long is too big, it could result in a strange double value.
              if(value.longValue() > 1000000000000l || value.longValue() < -1000000000000l ) {
                  return "";
              }
              BigDecimal myBigDecimal = new BigDecimal(value.longValue());
              //to convert the long to a double (currency with fractional digits)
              myBigDecimal = myBigDecimal.movePointLeft(2);
              double asDouble = myBigDecimal.doubleValue();
              if(asDouble == Double.NEGATIVE_INFINITY || asDouble == Double.POSITIVE_INFINITY) {
                  return "";
              }
              return super.toString(asDouble);
          }
      
      导入java.text.NumberFormat;
      导入java.util.Locale;
      导入javafx.util.converter.NumberStringConverter;
      公共类MyNumberStringConverter扩展了NumberStringConverter{
      公共MyNumberStringConverter(){
      超级();
      }
      公共MyNumberStringConverter(区域设置,字符串模式){
      超级(地点、模式);
      }
      公共MyNumberStringConverter(区域设置){
      超级(现场);
      }
      公共MyNumberStringConverter(NumberFormat NumberFormat){
      超级(数字格式);
      }
      公共MyNumberStringConverter(字符串模式){
      超级(模式);
      }
      @凌驾
      公共编号fromString(字符串值){
      //要转换文本字段给出的double,只需乘以100,如果有,则进行四舍五入
      数字rValue=Math.round(super.fromString(value).doubleValue()*100);
      返回rValue.longValue();
      }
      @凌驾
      公共字符串到字符串(数值){
      如果(值==null){
      返回“”;
      }
      //检查长值是否太大
      //如果long太大,可能会导致奇怪的双精度值。
      如果(value.longValue()>10000000000l | | value.longValue()<-10000000000l){
      返回“”;
      }
      BigDecimal myBigDecimal=新的BigDecimal(value.longValue());
      //将long转换为double(带小数位数的货币)
      myBigDecimal=myBigDecimal.movePointLeft(2);
      double asDouble=myBigDecimal.doubleValue();
      if(asDouble==Double.NEGATIVE | | asDouble==Double.NEGATIVE |{
      返回“”;
      }
      返回super.toString(asDouble);
      }
      
      Util类:

      import java.util.function.UnaryOperator;
      import javafx.scene.control.TextFormatter;
      
      public class Util {
      
          // This will filter the changes
          public static UnaryOperator<TextFormatter.Change> createFilter() {
              //this is a simple Regex to define the acceptable Chars
              String validEditingStateRegex = "[0123456789,.-]*";
              return change -> {
                  String text = change.getText();
                  //Check if something changed and just return if not
                  if (!change.isContentChange()) {
                      return change;
                  }
                  //check if the changed text validates against the regex
                  if (text.matches(validEditingStateRegex) || text.isEmpty()) {
                      //if valid return the change
                      return change;
                  }
                  //otherwise return null
                  return null;
              };
          }
      }
      
      import java.util.function.UnaryOperator;
      导入javafx.scene.control.TextFormatter;
      公共类Util{
      //这将过滤更改
      公共静态一元运算符createFilter(){
      //这是一个定义可接受字符的简单正则表达式
      字符串validEditingStateRegex=“[0123456789,.-]*”;
      返回更改->{
      String text=change.getText();
      //检查是否有更改,如果没有,请返回
      如果(!change.isContentChange()){
      回报变化;
      }
      //检查更改的文本是否根据正则表达式进行验证
      if(text.matches(validEditingStateRegex)| | text.isEmpty()){
      //如果有效,请返回更改
      回报变化;
      }
      //否则返回null
      返回null;
      };
      }
      }
      
      测试应用:

      import java.text.NumberFormat;
      import javafx.application.Application;
      import javafx.scene.Parent;
      import javafx.scene.Scene;
      import javafx.scene.control.Label;
      import javafx.scene.control.TextField;
      import javafx.scene.control.TextFormatter;
      import javafx.scene.layout.VBox;
      import javafx.stage.Stage;
      
      public class BindingExample extends Application {
      
          public static void main(String[] args) {
              launch(args);
          }
      
          @Override
          public void start(Stage primaryStage) throws Exception {
              Scene scene = new Scene(createBindingExample());
              primaryStage.setScene(scene);
              primaryStage.show();
          }
      
          //Creates just a sample gui with a Business Objekt 
          public static Parent createBindingExample() {
              VBox vbox = new VBox();
              SimpleBo myBo = new SimpleBo();
              TextField myTextField = new TextField();
              Label fooLabel = new Label();
      
              //Setting up the textField with a Formatter
              NumberFormat nFormat = NumberFormat.getInstance();
              //Define the integer and fractional digits
              nFormat.setMinimumIntegerDigits(1);
              nFormat.setMaximumFractionDigits(2);
              //setting up the TextFormatter with the NumberFormat and a Filter to limit the inputchars
              TextFormatter<Number> textFormatter = new TextFormatter<>(new MyNumberStringConverter(nFormat), 0l,
                      Util.createFilter());
              //Bind (Bidirectional) the BO currency value to the textformatter value
              textFormatter.valueProperty().bindBidirectional(myBo.currencyLongProperty());
              myTextField.setTextFormatter(textFormatter);
      
              //just to show the currency value, bind it to the label
              fooLabel.textProperty().bind(myBo.currencyLongProperty().asString());
      
              vbox.getChildren().add(myTextField);
              //just for spacing
              vbox.getChildren().add(new Label(" "));
              vbox.getChildren().add(fooLabel);
              return vbox;
          }
      }
      
      导入java.text.NumberFormat;
      导入javafx.application.application;
      导入javafx.scene.Parent;
      导入javafx.scene.scene;
      导入javafx.scene.control.Label;
      导入javafx.scene.control.TextField;
      导入javafx.scene.control.TextFormatter;
      导入javafx.scene.layout.VBox;
      导入javafx.stage.stage;
      公共类绑定示例扩展了应用程序{
      公共静态void main(字符串[]args){
      发射(args);
      }
      @凌驾
      public void start(Stage primaryStage)引发异常{
      场景=新场景(createBindingExample());
      初级阶段。场景(场景);
      primaryStage.show();
      }
      //仅创建一个带有业务对象的示例gui
      公共静态父createBindingExample(){
      VBox VBox=新的VBox();
      SimpleBo myBo=新SimpleBo();
      TextField myTextField=新建TextField();
      标签标签=新标签();
      //使用格式化程序设置文本字段
      NumberFormat info=NumberFormat.getInstance();
      //定义整数和小数位数
      信息格式设置最小整数位数(1);
      信息格式setMaximumFractionDigits(2);
      //使用NumberFormat和筛选器设置TextFormatter以限制输入字符
      TextFormatter TextFormatter=新的TextFormatter(新的MyNumberStringConverter(nFormat),0l,
      Util.createFilter());
      //将BO货币值绑定(双向)到textformatter值
      textFormatter.valueProperty().bindBidirectional(myBo.currencyLongProperty());
      myTextField.setTextFormatter(textFormatter);
      //为了显示货币值,请将其绑定到标签
      doubabel.textProperty().bind(myBo.currencyLongProperty().asString());
      vbox.getChildren().add(myTextField);
      //只是为了间隔
      vbox.getChildren().add(新标签(“”);
      vbox.getChildren().add(傻瓜标签);
      返回vbox;
      }
      }
      
      您可以将文本字段放在HBox中,并为货币符号添加一个标签。或者使用一个货币符号下拉框或其他任何东西。可以将数字格式与货币一起使用,这样格式就可以添加符号。但这还有一些其他缺点,所以我选择了这种方式。

      这里有一个解决方案(可能不是最好的,如果我能改进,请评论)

      Bo:

      import java.util.Random;
      
      import javafx.beans.property.LongProperty;
      import javafx.beans.property.SimpleLongProperty;
      
      public class SimpleBo {
              //a simple LongProperty to store the currency without fractional digits (56,81 € would be 5681)
              private LongProperty currencyLong = new SimpleLongProperty();
              public SimpleBo() {
                  setCurrencyLong(new Random().nextLong());
              }
              public final LongProperty currencyLongProperty() {
                  return this.currencyLong;
              }
              public final long getCurrencyLong() {
                  return this.currencyLongProperty().get();
              }
              public final void setCurrencyLong(final long currencyLong) {
                  this.currencyLongProperty().set(currencyLong);
              }
      }
      
      数字到字符串转换器:

      import java.text.NumberFormat;
      import java.util.Locale;
      
      import javafx.util.converter.NumberStringConverter;
      
      public class MyNumberStringConverter extends NumberStringConverter {
          public MyNumberStringConverter() {
              super();
          }
      
          public MyNumberStringConverter(Locale locale, String pattern) {
              super(locale, pattern);
          }
      
          public MyNumberStringConverter(Locale locale) {
              super(locale);
          }
      
          public MyNumberStringConverter(NumberFormat numberFormat) {
              super(numberFormat);
          }
      
          public MyNumberStringConverter(String pattern) {
              super(pattern);
          }
      
          @Override
          public Number fromString(String value) {
              //to transform the double, given by the textfield, just multiply by 100 and round if any left
              Number rValue = Math.round(super.fromString(value).doubleValue() * 100);
              return rValue.longValue();
          }
      
          @Override
          public String toString(Number value) {
              if(value == null) {
                  return "";
              }
              //Check for too big long value
              //If the long is too big, it could result in a strange double value.
              if(value.longValue() > 1000000000000l || value.longValue() < -1000000000000l ) {
                  return "";
              }
              BigDecimal myBigDecimal = new BigDecimal(value.longValue());
              //to convert the long to a double (currency with fractional digits)
              myBigDecimal = myBigDecimal.movePointLeft(2);
              double asDouble = myBigDecimal.doubleValue();
              if(asDouble == Double.NEGATIVE_INFINITY || asDouble == Double.POSITIVE_INFINITY) {
                  return "";
              }
              return super.toString(asDouble);
          }
      
      导入java.text.NumberFormat;
      导入java.util.Locale;
      导入javafx.util.converter.NumberStringConverter;
      公共类MyNumberStringConverter扩展了NumberStringConverter{
      公共MyNumberStringConverter(){
      超级();
      }
      公共MyNumberStringConverter(区域设置,字符串模式){
      超级(地点、模式);