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

如何为单个JavaFX按钮创建按顺序触发的多个onAction监听器?

JavaFX黑杰克游戏分步输入交互解决方案

不需要创建新场景,通过追踪当前交互步骤,在同一个按钮监听器里分阶段处理输入即可解决问题。核心是用一个变量记录当前处于哪个流程节点,每次点击按钮时根据节点执行对应逻辑,完成后切换到下一个节点。

修改后的完整代码

package blackjack;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class BlackJack extends Application {

    //"topPane" will reveal the area to be maniplated by player
    public GridPane getTopPane(){
        GridPane topPane = new GridPane();
        
        // 步骤追踪变量:0=输入姓名,1=输入存款金额,2=输入下注金额,3=回合开始
        int[] currentStep = {0};

        //first section
        TextArea gameplayTA = new TextArea("Welcome to the table.\nWhat is your name?");
        gameplayTA.setEditable(false);
        gameplayTA.setPrefRowCount(3);
        gameplayTA.setPrefColumnCount(3);
        
        HBox userEntryHB = new HBox();
        TextField userEntryTF = new TextField("");
        Button userEntryBtn = new Button("ENTER");
        userEntryBtn.disableProperty().bind(userEntryTF.textProperty().isEmpty());
        
        userEntryHB.getChildren().addAll(userEntryTF, userEntryBtn);
        HBox.setMargin(userEntryTF, new Insets(10, 5, 10, 0));
        HBox.setMargin(userEntryBtn, new Insets(10, 5, 10, 0));
        
        VBox gameplayVB = new VBox();
        gameplayVB.getChildren().addAll(gameplayTA, userEntryHB);
        VBox.setMargin(gameplayTA, new Insets(10, 5, 5, 10));
        VBox.setMargin(userEntryHB, new Insets(0, 0, 0, 10));
        
        topPane.getChildren().add(gameplayVB);
        GridPane.setConstraints(gameplayVB, 0, 0);
        
        //second section - scores/bank/bet
        TextField playerBankTF = new TextField("");
        playerBankTF.setEditable(false);
        TextField compBankTF = new TextField("");
        compBankTF.setEditable(false);
        TextField betAmountTF = new TextField("");
        betAmountTF.setEditable(false);
        TextField playerScoreTF = new TextField("");
        playerScoreTF.setEditable(false);
        TextField compScoreTF = new TextField("");
        compScoreTF.setEditable(false);
        
        playerBankTF.setPrefWidth(80);
        compBankTF.setPrefWidth(80);
        betAmountTF.setPrefWidth(80);
        playerScoreTF.setPrefWidth(40);
        compScoreTF.setPrefWidth(40);
        
        Label playerBankLbl = new Label("Player Bank: ", playerBankTF);
        Label compBankLbl = new Label("Computer Bank: ", compBankTF);
        Label betAmountLbl = new Label("Bet Amount: ", betAmountTF);
        Label playerScoreLbl = new Label("Player Score: ", playerScoreTF);
        Label compScoreLbl = new Label("Computer Score: ", compScoreTF);
        
        playerBankLbl.setContentDisplay(ContentDisplay.RIGHT);
        compBankLbl.setContentDisplay(ContentDisplay.RIGHT);
        betAmountLbl.setContentDisplay(ContentDisplay.RIGHT);
        playerScoreLbl.setContentDisplay(ContentDisplay.RIGHT);
        compScoreLbl.setContentDisplay(ContentDisplay.RIGHT);
        
        HBox hbOne = new HBox();
        hbOne.getChildren().addAll(playerBankLbl, compBankLbl);
        HBox.setMargin(playerBankLbl, new Insets(20, 10, 10, 10));
        HBox.setMargin(compBankLbl, new Insets(20, 10, 10, 10));
        
        HBox hbTwo = new HBox();
        hbTwo.getChildren().add(betAmountLbl);
        HBox.setMargin(betAmountLbl, new Insets(0, 0, 10, 70));
        
        HBox hbThree = new HBox();
        hbThree.getChildren().addAll(playerScoreLbl, compScoreLbl);
        HBox.setMargin(playerScoreLbl, new Insets(0, 10, 10, 30));
        HBox.setMargin(compScoreLbl, new Insets(0, 10, 10, 10));
        
        VBox statsVB = new VBox();
        statsVB.getChildren().addAll(hbOne, hbTwo, hbThree);
        
        topPane.getChildren().add(statsVB);
        GridPane.setConstraints(statsVB, 2, 0);
        
        //create new player
        Player player = new Player();
        //create new computer player
        Computer computer = new Computer();
        
        // 统一按钮监听器,根据步骤处理逻辑
        userEntryBtn.setOnAction(e -> {
            String input = userEntryTF.getText().trim();
            userEntryTF.clear();
            
            switch(currentStep[0]){
                case 0: // 处理姓名输入
                    player.setName(input);
                    gameplayTA.setText("Hello, " + player.getName() + ".\nLet's add money" +
                            " to your account.\nEnter $$ amount.");
                    currentStep[0] = 1; // 切换到存款步骤
                    break;
                    
                case 1: // 处理存款金额输入
                    try {
                        double deposit = Double.parseDouble(input);
                        player.setBank(deposit);
                        playerBankTF.setText(String.format("%.2f", deposit));
                        gameplayTA.setText("Your bank now has $" + String.format("%.2f", deposit) +
                                "\nEnter your bet amount for this round.");
                        currentStep[0] = 2; // 切换到下注步骤
                    } catch(NumberFormatException ex){
                        gameplayTA.setText("Invalid amount. Please enter a valid number.\nEnter $$ amount.");
                    }
                    break;
                    
                case 2: // 处理下注金额输入
                    try {
                        double bet = Double.parseDouble(input);
                        if(bet > 0 && bet <= player.getBank()){
                            player.setBet(bet);
                            betAmountTF.setText(String.format("%.2f", bet));
                            gameplayTA.setText("Bet placed: $" + String.format("%.2f", bet) +
                                    "\nPress ENTER to start the round!");
                            currentStep[0] = 3; // 切换到回合开始步骤
                        } else {
                            gameplayTA.setText("Invalid bet amount. Must be positive and within your bank.\nEnter your bet amount.");
                        }
                    } catch(NumberFormatException ex){
                        gameplayTA.setText("Invalid amount. Please enter a valid number.\nEnter your bet amount.");
                    }
                    break;
                    
                case 3:
                    // 这里接入你的业务逻辑,比如发牌、计算分数等
                    gameplayTA.setText("Round started!\nYour cards: ...");
                    // 可继续扩展后续步骤,比如Hit/Stand选择
                    currentStep[0] = 4;
                    break;
            }
        });
        
        return topPane;
    }

    @Override
    public void start(Stage primaryStage) {
        Scene scene1 = new Scene(getTopPane(), 600, 600);
        primaryStage.setTitle("BLACKJACK");
        primaryStage.setScene(scene1);
        primaryStage.show();
    }

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

关键修改说明

  • 使用int[] currentStep作为步骤追踪变量(用数组是因为Lambda表达式中需访问effectively final变量)
  • 将所有交互逻辑整合到同一个按钮onAction监听器中,通过switch分支处理不同步骤的输入
  • 每完成一个步骤后,更新currentStep的值,同时清空输入框、更新TextArea提示,引导用户进入下一个环节
  • 加入输入合法性校验(金额格式、下注金额范围),避免无效输入影响流程

这种方式无需切换场景,所有交互在同一界面完成,逻辑清晰且易于扩展后续游戏步骤。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 23:05:09