You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开发JavaFX动态掩码金额TextField:仿ATM输入模式

实现ATM风格的JavaFX数字输入框

我之前在金融类JavaFX项目里正好做过完全匹配你需求的输入控件——初始默认显示0.00,用户输入数字时从右往左逐位替换,自动维护两位小数的金额格式,比如输入三次9再输入0,会依次显示0.09→0.99→9.99→99.90。下面是完整的可落地实现方案:

核心逻辑思路

  • 全程强制保持两位小数的金额格式,不允许用户手动输入小数点或非数字字符
  • 把输入的数字当作整数序列处理:当前值去掉小数点转成整数,输入新数字时左移一位(乘以10)加上新数字,再除以100转成两位小数的字符串
  • 可配置最大输入金额,避免超出业务允许的范围

完整代码实现

我们可以自定义一个继承自TextField的控件,封装所有输入逻辑:

import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;

public class ATMNumberTextField extends TextField {

    private static final String DECIMAL_FORMAT = "%.2f";
    // 可根据业务需求调整最大允许输入的金额
    private static final double MAX_ALLOWED_AMOUNT = 9999.99;

    public ATMNumberTextField() {
        super();
        // 初始值设置为0.00
        setText("0.00");
        // 禁止用户直接编辑文本,确保输入逻辑完全由我们控制
        setEditable(false);
        // 监听键盘输入事件
        addEventFilter(KeyEvent.KEY_TYPED, this::processDigitInput);
        addEventFilter(KeyEvent.KEY_PRESSED, this::processBackspace);
    }

    private void processDigitInput(KeyEvent event) {
        char inputChar = event.getCharacter().charAt(0);
        // 只允许数字输入,过滤其他字符
        if (!Character.isDigit(inputChar)) {
            event.consume();
            return;
        }

        // 解析当前显示的金额为整数(去掉小数点)
        String currentText = getText().replace(".", "");
        long currentValue = Long.parseLong(currentText);
        // 计算新值:左移一位加上输入的数字
        long newValue = currentValue * 10 + Character.getNumericValue(inputChar);
        // 转成金额并检查是否超出最大值
        double newAmount = newValue / 100.0;
        if (newAmount > MAX_ALLOWED_AMOUNT) {
            event.consume();
            return;
        }
        // 更新显示为两位小数格式
        setText(String.format(DECIMAL_FORMAT, newAmount));
    }

    private void processBackspace(KeyEvent event) {
        // 处理退格键,实现从右往左删除一位
        if (event.getCode().equals(javafx.scene.input.KeyCode.BACK_SPACE)) {
            String currentText = getText().replace(".", "");
            if (currentText.length() <= 1) {
                // 只剩最后一位,重置为初始值0.00
                setText("0.00");
            } else {
                // 右移一位(除以10),重新格式化显示
                long currentValue = Long.parseLong(currentText);
                long newValue = currentValue / 10;
                double newAmount = newValue / 100.0;
                setText(String.format(DECIMAL_FORMAT, newAmount));
            }
            event.consume();
        }
    }

    // 对外提供获取当前金额的方法
    public double getCurrentAmount() {
        return Double.parseDouble(getText());
    }
}

关键代码解释

  • setEditable(false):禁止用户手动选中或修改文本,避免破坏我们的金额格式,所有输入都通过键盘事件处理
  • KEY_TYPED事件处理:过滤非数字输入,核心逻辑是把当前金额转成整数序列,新输入的数字追加到末尾(相当于左移一位加数字),再转成两位小数格式
  • KEY_PRESSED事件处理:专门处理退格键,实现从右往左删除一位,当只剩最后一位时重置为0.00
  • MAX_ALLOWED_AMOUNT:可根据业务需求调整,比如限制最大输入99999.99

使用示例

在你的JavaFX界面中直接实例化这个控件即可:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ATMInputDemo extends Application {
    @Override
    public void start(Stage primaryStage) {
        ATMNumberTextField atmInput = new ATMNumberTextField();
        // 可以设置控件的样式,比如调整字体大小、对齐方式
        atmInput.setStyle("-fx-font-size: 18px; -fx-alignment: center-right;");
        
        VBox root = new VBox(10, atmInput);
        root.setStyle("-fx-padding: 20px;");
        
        Scene scene = new Scene(root, 250, 80);
        primaryStage.setTitle("ATM Style Input");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

测试一下你描述的场景:

  • 第一次按9 → 显示0.09
  • 第二次按9 → 显示0.99
  • 第三次按9 → 显示9.99
  • 第四次按0 → 显示99.90
  • 按退格键 → 依次回到9.99→0.99→0.09→0.00

内容的提问来源于stack exchange,提问作者Samuel Santos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:56:52