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!");
}
}
}
}
所以这只是基本的控制台结构,我遵循我的 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!");
}
}
}
}