So this is just the basic console structure, I follow for my GUI program, however, I noticed whenever I enter one of the options to prompt a screen it would end up freezing, I am aware that it's obviously because of the infinite while loop, but I had no other way of expecting the console to re-prompt as soon as the window is closed. Which was why I relied on the while loop, please can someone provide me with a solution for this.
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));
}
}
You should not perform long computation in the FXThread and a blocking method (like Scanner#nextLine) can be very long...
You have to request the option on a separated thread. Depending on the selected option, you may have to perform some actions to modify the GUI. In that case you MUST do that in the FXThread by using the Platform#runLater method.
Below is a quick example using 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!");
}
}
}
}
Here is a sample after the comment by @Genesis_Kitty (several optimizations could be done for a better code):
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!");
}
}
}
}