JavaFX switch case 控制台,当输入选项时 window 会冻结吗?

JavaFX switch case console, when option is entered the window becomes frozen?

所以这只是基本的控制台结构,我遵循我的 GUI 程序,但是,我注意到每当我输入其中一个选项来提示屏幕时它最终会冻结,我知道这显然是因为无限 while 循环,但我没有其他方法可以期望控制台在 window 关闭后立即重新提示。这就是我依赖 while 循环的原因,请有人为此提供解决方案。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.util.Scanner;

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

        @Override
        public void start(Stage primaryStage) throws Exception {

            BorderPane borderPane = new BorderPane();
            labelStatement:
            while (true) {
                System.out.println("Press a for method a");
                System.out.println("Press b for method b");
                System.out.println("Enter q to end program!");

                Scanner sc = new Scanner(System.in);
                String input = sc.nextLine().toLowerCase();
                switch (input) {
                    case "a":
                        optionA(borderPane, primaryStage);
                        primaryStage.show();
                        break;
                    case "b":
                        optionB(borderPane, primaryStage);
                        primaryStage.show();
                        break;
                    case "q":
                        break labelStatement;
                    default:
                        System.out.println("wrong option!");
                }
            }
        }



    private void optionA(BorderPane borderPane, Stage primaryStage) {
            primaryStage.setScene(new Scene(borderPane, 1000, 500));
        }

    private void optionB(BorderPane borderPane, Stage primaryStage) {
        primaryStage.setScene(new Scene(borderPane, 1000, 500));

    }

}

您不应在 FXThread 中执行长时间计算,阻塞方法(如 Scanner#nextLine)可能会非常长...

您必须在单独的线程上请求该选项。根据所选选项,您可能必须执行一些操作来修改 GUI。在那种情况下,您必须使用 Platform#runLater 方法在 FXThread 中执行此操作。

下面是一个使用 Java 8 的简单示例:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.lang.annotation.Native;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.function.BooleanSupplier;

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


    @Override
    public void start(Stage primaryStage) throws Exception {
        final BorderPane borderPane = new BorderPane();
        borderPane.setCenter(new Label("Select an Option"));

        final Map<String, BooleanSupplier> actionMap = new HashMap<>();
        actionMap.put("a", () -> {
            optionA(borderPane);
            return false;
        });
        actionMap.put("b", () -> {
            optionB(borderPane);
            return false;
        });
        actionMap.put("q", () -> {
            closeGui(primaryStage);
            return true;
        });

        final Thread askOptionThread = new Thread(() -> askOption(actionMap));
        askOptionThread.setDaemon(true);
        askOptionThread.start();

        System.out.println("SHOW");
        primaryStage.setTitle("Options");
        primaryStage.setScene(new Scene(borderPane, 600, 400));
        primaryStage.centerOnScreen();
        primaryStage.show();
    }


    private void closeGui(Stage primaryStage) {
        Platform.runLater(primaryStage::hide);
    }

    private void optionA(BorderPane borderPane) {
        Platform.runLater(() -> {
            borderPane.setCenter(new Label("Option A selected"));
        });
    }

    private void optionB(BorderPane borderPane) {
        Platform.runLater(() -> {
            borderPane.setCenter(new Label("Option B selected"));
        });
    }


    private static void askOption(Map<String, BooleanSupplier> actionMap) {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Press a for method a");
            System.out.println("Press b for method b");
            System.out.println("Enter q to end program!");

            Scanner sc = new Scanner(System.in);
            String input = sc.nextLine().toLowerCase();
            final BooleanSupplier action = actionMap.get(input);
            if (action != null) {
                boolean shouldQuit = action.getAsBoolean();
                if (shouldQuit) {
                    break;
                }
            } else {
                System.out.println("wrong option!");
            }
        }

    }


}

这是@Genesis_Kitty评论后的示例(可以进行一些优化以获得更好的代码):

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

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


    @Override
    public void start(Stage primaryStage) throws Exception {

        final Map<String, Runnable> actionMap = new HashMap<>();
        actionMap.put("a", () -> optionA(primaryStage));
        actionMap.put("b", () -> optionB(primaryStage));
        actionMap.put("q", Platform::exit);

        Platform.setImplicitExit(false); //needed or your application will exit
        primaryStage.setTitle("Options");
        primaryStage.showingProperty().addListener((l,o,s) -> {if (!s) { launchAskOption(actionMap);}});
        launchAskOption(actionMap);
    }

    private void launchAskOption(Map<String, Runnable> actionMap) {
        final Thread askOptionThread = new Thread(() -> askOption(actionMap));
        askOptionThread.start();
    }

    private void optionA(Stage primaryStage) {
        final BorderPane borderPane = new BorderPane();
        borderPane.setCenter(new Label("Option A selected"));
        primaryStage.setScene(new Scene(borderPane, 600,400));
        primaryStage.centerOnScreen();
        primaryStage.show();
    }

    private void optionB(Stage primaryStage) {
        final BorderPane borderPane = new BorderPane();
        borderPane.setCenter(new Label("Option B selected"));
        primaryStage.setScene(new Scene(borderPane, 600,400));
        primaryStage.centerOnScreen();
        primaryStage.show();
    }

    private static void askOption(Map<String, Runnable> actionMap) {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("Press a for method a");
            System.out.println("Press b for method b");
            System.out.println("Enter q to end program!");

            Scanner sc = new Scanner(System.in);
            String input = sc.nextLine().toLowerCase();
            final Runnable action = actionMap.get(input);
            if (action != null) {
                Platform.runLater(action);
                break;
            } else {
                System.out.println("wrong option!");
            }
        }
    }

}