NumberFormatException:对于输入字符串:TextField 中的 "XXX,XX",与语言环境相关

NumberFormatException: For input string: "XXX,XX" in TextField, related to locale

我有一个控制器 class 可以加载相应选择的场景。我称它为 "CMenu".

/*** Other methods that load other menu entries ***/

/**
 * Menu de Usuarios
 * 
 * @param event
 * @throws Exception
 */
public void menuUsuarios(ActionEvent event) throws Exception {
    try {
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/Usuarios.fxml"));
        Scene scene = new Scene(root);
        scene.getStylesheets().add(getClass().getResource("/styles/application.css").toExternalForm());
        Stage stage = new Stage();
        stage.setTitle("Menu de usuarios");
        stage.setScene(scene);
        stage.setResizable(false);
        // Llamamos a la ventana de menu
        stage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * Menu de Inventario
 * 
 * @param event
 * @throws Exception
 */
public void menuProductos(ActionEvent event) throws Exception {
    try {
        Locale.setDefault(new Locale("es"));
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/Productos.fxml"));
        Scene scene = new Scene(root);
        scene.getStylesheets().add(getClass().getResource("/styles/application.css").toExternalForm());
        Stage stage = new Stage();
        stage.setTitle("Menu de Productos");
        stage.setScene(scene);
        stage.setResizable(false);
        stage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

/**
 * Menu de Empleados
 * 
 * @param event
 * @throws Exception
 */
public void menuEmpleados(ActionEvent event) throws Exception {
    try {
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/Empleados.fxml"));
        Scene scene = new Scene(root);
        scene.getStylesheets().add(getClass().getResource("/styles/application.css").toExternalForm());
        Stage stage = new Stage();
        stage.setTitle("Menu de Empleados");
        stage.setScene(scene);
        stage.setResizable(false);
        stage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

    /*** Other methods that load other menu entries ***/

有 "products" 菜单,看起来像这样。

Product menu

当我输入成本并设置利润时,使用 onKeyEvent 计算价格,格式为:“123.456,99”。反之亦然。

txtUtil.setOnKeyReleased(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent event) {
            if (txtCosto.getText() != null && txtUtil.getText() != null && txtPrecio.getText() != null) {
                try {
                    costo = Double.parseDouble(txtCosto.getText());
                    util = Double.parseDouble(txtUtil.getText());
                    precio = (costo / (((util / 100) - 1) * (-1)));
                    txtPrecio.setText(String.valueOf(String.format("%.2f", precio)));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                JOptionPane.showMessageDialog(null, "error en algo");
            }

        }
    });
        txtPrecio.setOnKeyReleased(new EventHandler<KeyEvent>() {
        @Override
        public void handle(KeyEvent event) {
            if (txtCosto.getText() != null && txtUtil.getText() != null && txtPrecio.getText() != null) {
                try {
                    costo = Double.parseDouble(txtCosto.getText());
                    precio = Double.parseDouble(txtPrecio.getText());
                    util = ((costo / precio) - 1) * -100;
                    txtUtil.setText(String.valueOf((double) Math.round(util * 100) / 100));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                JOptionPane.showMessageDialog(null, "error");
            }
        }
    });
}

因此,当我在价格 TextField 中释放密钥时,出现此错误(还有其他错误,但此处未提及)。

java.lang.NumberFormatException: For input string: "21428,57"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at ajfmo.sislic.controlador.CProductos.handle(CProductos.java:164)
at ajfmo.sislic.controlador.CProductos.handle(CProductos.java:1)

我看到问题出在 ajfmo.sislic.controlador.CProductos$3.handle(CProductos.java:164),但我发现真正的问题是场景获取的默认语言环境,我更改为 en 并且问题消失了,但是如果 我想保留我的默认语言环境而不出现该错误怎么办?

除了记录被保存到 MySQL 数据库之外,如果我更改了语言环境,我会有问题吗?

非常感谢您提前阅读本文。

要以与语言环境相关的方式(包括分组字符和与语言环境相关的小数点分隔符)将文本解析为数值,请使用 DecimalFormat 对象。

这是一个非常快速的演示,应该很容易适应您的应用程序:

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;

public class DecimalFormatTest {

    public static void main(String[] args) throws ParseException {

        // use system default locale:
        // NumberFormat format = DecimalFormat.getInstance();

        // or specify the locale explicitly:
        NumberFormat format = DecimalFormat.getInstance(new Locale("es", "VE"));

        String text = "123.456,01" ;
        double value = format.parse(text).doubleValue();
        System.out.println("Parsed value as double: " +value);
        System.out.println("Value formatted again as text: " + format.format(value));
    }

}

这给出了输出

Parsed value as double: 123456.01
Value formatted again as text: 123.456,01

Double.valueOf,并扩展为 Double.parseDouble,不考虑浮点数的国际表示。 Double.valueOf 上的 javadoc 声明如下:

要解释浮点值的本地化字符串表示,请使用 java.text.NumberFormat.

的子类

要获取 NumberFormat 的本地化版本,请使用它的 getInstance 方法。所以,你代码中的以下两行,

costo = Double.parseDouble(txtCosto.getText());
precio = Double.parseDouble(txtPrecio.getText());

应该改为,

NumberFormat nf = NumberFormat.getNumberInstance(); // Use JVM default locale
costco = nf.parse(txtCosto.getText()).doubleValue();
precio = nf.parse(txtPrecio.getText()).doubleValue();