在Java程序中调用JavaFX并等待等待退出,然后再运行更多代码
在我的java程序中,我给用户一些选项,其中一个调用JavaFX程序来显示一些内容。我只想在Java程序中运行更多的代码,当调用的JavaFX实际退出时,可能需要5秒,可能需要一分钟。理想情况下,我想要的是类似于Android的东西。我们调用在Java程序中调用JavaFX并等待等待退出,然后再运行更多代码,java,javafx,wait,onactivityresult,startactivityforresult,Java,Javafx,Wait,Onactivityresult,Startactivityforresult,在我的java程序中,我给用户一些选项,其中一个调用JavaFX程序来显示一些内容。我只想在Java程序中运行更多的代码,当调用的JavaFX实际退出时,可能需要5秒,可能需要一分钟。理想情况下,我想要的是类似于Android的东西。我们调用startActivityForResult(),然后等待调用onActivityResult()。 在我的情况下,我如何才能实现类似的行为 我编写了这段代码,试图复制我遇到的问题。这是一个类似的想法,但不知何故,它调用了JavaFX,进入循环的开始,并从用
startActivityForResult()
,然后等待调用onActivityResult()
。
在我的情况下,我如何才能实现类似的行为
我编写了这段代码,试图复制我遇到的问题。这是一个类似的想法,但不知何故,它调用了JavaFX,进入循环的开始,并从用户那里毫无问题地检索输入。在我的另一个程序中,当线程“main”java.util.InputMismatchException返回扫描输入时,我总是在线程“main”java.util.InputMismatchException中得到异常。但正如我所说,理想情况下,我只希望在JavaFX应用程序关闭后运行更多代码
package JavaCallsJavaFXandWaits;
import java.util.Scanner;
import javafx.application.Application;
public class MyJavaProgram {
public static void main(String[] args) {
int input;
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("0 - exit");
System.out.println("1 - display something to me");
input = scanner.nextInt();
switch (input) {
case 0:
break;
case 1:
Application.launch(JavaCallsJavaFXandWaits.MyJavaFXProgram.class, null);
// how to get notified of MyJavaFXProgram exit? I only want to run code after it exits
break;
}
if (input == 0) break;
}
}
}
package JavaCallsJavaFXandWaits;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class MyJavaFXProgram extends Application {
@Override
public void start(Stage primaryStage) {
Text oText = new Text("My JavaFXProgram");
StackPane root = new StackPane();
root.getChildren().add(oText);
Scene scene = new Scene(root, 800, 600);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
edit1:
我刚刚注意到,如果我尝试两次显示某个内容(例如:选择1,关闭JavaFX应用程序,然后再次选择1),它会在线程“main”java.lang.IllegalStateException中出现异常崩溃:不能多次调用应用程序启动。在这段代码中,JavaFX应用程序似乎也没有正确退出 您的代码无法正常工作,因为它不适合JavaFX应用程序的生命周期,而JavaFX应用程序的生命周期在的API文档中有完整的文档记录。简而言之,Application
类代表整个应用程序(或者可能是应用程序的生命周期)
要在JavaFX中显示窗口,必须在FX应用程序线程上执行此操作,并且必须启动FX工具箱才能启动此线程(除其他外)。Application.launch()
方法启动FX工具箱,启动FX应用程序线程,创建应用程序类的实例,对该实例调用init()
,然后对该实例调用start()
(对start()
的调用发生在FX应用程序线程上)
作为,Application.launch()
将阻塞(不返回),直到FX toolkit关闭(即应用程序退出),并且只能调用一次。(因为它代表整个应用程序,所以这是有意义的,没有办法避免调用它两次。)
从用户的角度来看,您的应用程序结构也没有任何意义。为什么要求用户与命令行交互以向基于GUI的应用程序提供选项?您应该在GUI中显示这些选项。只需在启动时显示包含选项的窗口,然后显示与所选选项对应的窗口。如果要确保用户在所选选项完成之前无法返回到原始窗口,只需将新窗口设置为模态
例如,如果您重构MyJavaFXProgram
,使其不是应用程序
子类(您应该这样做,因为它不是应用程序的起点):
那你就可以了
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.stage.Modality;
import javafx.stage.Stage;
public class MyJavaProgram extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
Button showMeSomethingButton = new Button("Show me something");
showMeSomethingButton.setOnAction(e -> {
MyJavaFXProgram myProgram = new MyJavaFXProgram();
showInModalWindow(myProgram.getView());
});
Button exitButton = new Button("Exit");
exitButton.setOnAction(e -> Platform.exit());
VBox root = new VBox(10, exitButton, showMeSomethingButton);
root.setPadding(new Insets(20));
root.setAlignment(Pos.CENTER);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
private void showInModalWindow(Parent view) {
Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setScene(new Scene(view));
stage.show();
}
}
如果您真的想从命令行驱动所有这一切(老实说,我看不出这样做的正当理由),那么它会变得很棘手,您必须在某个时候管理线程之间的交互。最简单的方法可能是确保FX工具箱在应用程序启动时启动,然后或多或少地按照代码中的方式进行操作,但要再次重构MyJavaFXProgram
,使其不是application
的子类。通过创建JFXPanel
,启动FXToolkit是一种黑客行为,但这确实是一种黑客行为,我更愿意通过创建一个实际上什么都不做的应用程序类,调用launch()
,并等待初始化完成来显式启动FXToolkit。我在对的回答中展示了如何做到这一点,所以我将从那里借用这个解决方案。以下是用于启动FX toolkit的应用程序
类(但不是您执行的主类):
我们的想法是调用Application.launch(FXStarter.class)
,但是由于launch()
阻塞,您需要在后台线程上执行此操作。因为这意味着后续代码可能(可能会)在launch()
实际完成您需要它完成的工作之前执行,所以您需要等待它完成它的工作,您可以使用FXStarter.awaitFXToolkit()
。然后可以执行循环。唯一需要担心的是确保在FX应用程序线程上创建并显示新窗口。因此,您的MyJavaProgram
现在看起来像:
import java.util.Scanner;
import java.util.concurrent.FutureTask;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MyJavaProgram {
public static void main(String[] args) throws Exception {
// start FX toolkit on background thread:
new Thread(() -> Application.launch(FXStarter.class)).start();
// wait for toolkit to start:
FXStarter.awaitFXToolkit();
// make sure closing first window does not exit FX toolkit:
Platform.setImplicitExit(false);
int input;
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("0 - exit");
System.out.println("1 - display something to me");
input = scanner.nextInt();
switch (input) {
case 0:
break;
case 1:
// task to show UI:
FutureTask<Void> showProgramTask = new FutureTask<>(() -> {
MyJavaFXProgram program = new MyJavaFXProgram();
Stage stage = new Stage();
stage.setScene(new Scene(program.getView(), 400, 400));
stage.setOnShown(e -> {
stage.toFront();
stage.requestFocus();
});
// showAndWait will block execution until window is hidden:
stage.showAndWait();
return null ;
});
// show UI on FX Application Thread:
Platform.runLater(showProgramTask);
// block until task completes (i.e. window is hidden):
showProgramTask.get() ;
break;
}
if (input == 0) break;
}
// all done, exit FX toolkit:
Platform.exit();
scanner.close();
}
}
import java.util.Scanner;
导入java.util.concurrent.FutureTask;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.scene.scene;
导入javafx.stage.stage;
公共类MyJavaProgram{
公共静态void main(字符串[]args)引发异常{
//在后台线程上启动FX toolkit:
新线程(()->Application.launch(FXStarter.class)).start();
//等待工具箱启动:
FXStarter.awaitFXToolkit();
//确保关闭第一个窗口不会退出FX toolkit:
Platform.setImplicitExit(false);
int输入;
扫描仪=新的扫描仪(System.in);
while(true){
System.out.println(“0-退出”);
System.out.println(“1-向我显示某物”);
输入=scanner.nextInt();
开关(输入){
案例0:
打破
案例1:
//要显示UI的任务:
FutureTask showProgramTask=新的FutureTask(()->{
MyJavaFXProgram=新的MyJavaFXProgram();
阶段=新阶段();
import java.util.concurrent.CountDownLatch;
import javafx.application.Application;
import javafx.stage.Stage;
public class FXStarter extends Application {
private static final CountDownLatch latch = new CountDownLatch(1);
public static void awaitFXToolkit() throws InterruptedException {
latch.await();
}
@Override
public void init() {
latch.countDown();
}
@Override
public void start(Stage primaryStage) {
// no-op
}
}
import java.util.Scanner;
import java.util.concurrent.FutureTask;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class MyJavaProgram {
public static void main(String[] args) throws Exception {
// start FX toolkit on background thread:
new Thread(() -> Application.launch(FXStarter.class)).start();
// wait for toolkit to start:
FXStarter.awaitFXToolkit();
// make sure closing first window does not exit FX toolkit:
Platform.setImplicitExit(false);
int input;
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("0 - exit");
System.out.println("1 - display something to me");
input = scanner.nextInt();
switch (input) {
case 0:
break;
case 1:
// task to show UI:
FutureTask<Void> showProgramTask = new FutureTask<>(() -> {
MyJavaFXProgram program = new MyJavaFXProgram();
Stage stage = new Stage();
stage.setScene(new Scene(program.getView(), 400, 400));
stage.setOnShown(e -> {
stage.toFront();
stage.requestFocus();
});
// showAndWait will block execution until window is hidden:
stage.showAndWait();
return null ;
});
// show UI on FX Application Thread:
Platform.runLater(showProgramTask);
// block until task completes (i.e. window is hidden):
showProgramTask.get() ;
break;
}
if (input == 0) break;
}
// all done, exit FX toolkit:
Platform.exit();
scanner.close();
}
}