14

如何在java中多次调用launch()我得到一个异常“主错误:java.lang.IllegalStateException:应用程序启动不能被多次调用”

当请求到来时,我在我的 java 应用程序中创建了 rest cleint,它调用 javafx 并在完成 webview 操作后打开 webview,正在使用 Platform.exit() 方法关闭 javafx 窗口。当第二个请求到来时,我收到此错误,如何解决此错误。

JavaFx 应用程序代码:

public class AppWebview extends Application  {

    public static Stage stage;

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

        stage = _stage;
        StackPane root = new StackPane();

        WebView view = new WebView();

        WebEngine engine = view.getEngine();
        engine.load(PaymentServerRestAPI.BROWSER_URL);
        root.getChildren().add(view);
        engine.setJavaScriptEnabled(true);
        Scene scene = new Scene(root, 800, 600);
        stage.setScene(scene);

        engine.setOnResized(new EventHandler<WebEvent<Rectangle2D>>() {
            public void handle(WebEvent<Rectangle2D> ev) {
                Rectangle2D r = ev.getData();
                stage.setWidth(r.getWidth());
                stage.setHeight(r.getHeight());
            }
        });

        JSObject window = (JSObject) engine.executeScript("window");
        window.setMember("app", new BrowserApp());

        stage.show();

    }

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

RestClient 方法:调用 JavaFX 应用程序

// method 1 to lanch javafx
javafx.application.Application.launch(AppWebview.class);

// method 2 to lanch javafx
String[] arguments = new String[] {"123"};
AppWebview .main(arguments);
4

3 回答 3

27

您不能launch()多次调用 JavaFX 应用程序,这是不允许的。

从javadoc:

It must not be called more than once or an exception will be thrown.

定期显示窗口的建议

  1. 只需调用Application.launch()一次。
  2. 使用 保持 JavaFX 运行时在后台运行Platform.setImplicitExit(false),这样当您隐藏最后一个应用程序窗口时,JavaFX 不会自动关闭。
  3. 下次您需要另一个窗口时,将窗口show()调用包装在 中Platform.runLater(),以便在 JavaFX 应用程序线程上执行调用。

对于此方法的简短摘要实现:

如果您正在混合 Swing,您可以使用JFXPanel而不是Application,但使用模式将类似于上面概述的模式。

Wumpus 样本

这个例子比它需要的要复杂一些,因为它还涉及定时器任务。但是,它确实提供了一个完整的独立示例,有时可能会有所帮助。

import javafx.animation.PauseTransition;
import javafx.application.*;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;
import javafx.util.Duration;

import java.util.*;

// hunt the Wumpus....
public class Wumpus extends Application {
    private static final Insets SAFETY_ZONE = new Insets(10);
    private Label cowerInFear = new Label();
    private Stage mainStage;

    @Override
    public void start(final Stage stage) {
        // wumpus rulez
        mainStage = stage;
        mainStage.setAlwaysOnTop(true);

        // the wumpus doesn't leave when the last stage is hidden.
        Platform.setImplicitExit(false);

        // the savage Wumpus will attack
        // in the background when we least expect
        // (at regular intervals ;-).
        Timer timer = new Timer();
        timer.schedule(new WumpusAttack(), 0, 5_000);

        // every time we cower in fear
        // from the last savage attack
        // the wumpus will hide two seconds later.
        cowerInFear.setPadding(SAFETY_ZONE);
        cowerInFear.textProperty().addListener((observable, oldValue, newValue) -> {
            PauseTransition pause = new PauseTransition(
                    Duration.seconds(2)
            );
            pause.setOnFinished(event -> stage.hide());
            pause.play();
        });

        // when we just can't take it  anymore,
        // a simple click will quiet the Wumpus,
        // but you have to be quick...
        cowerInFear.setOnMouseClicked(event -> {
            timer.cancel();
            Platform.exit();
        });

        stage.setScene(new Scene(cowerInFear));
    }

    // it's so scary...
    public class WumpusAttack extends TimerTask {
        private String[] attacks = {
                "hugs you",
                "reads you a bedtime story",
                "sings you a lullaby",
                "puts you to sleep"
        };

        // the restaurant at the end of the universe.
        private Random random = new Random(42);

        @Override
        public void run() {
            // use runlater when we mess with the scene graph,
            // so we don't cross the streams, as that would be bad.
            Platform.runLater(() -> {
                cowerInFear.setText("The Wumpus " + nextAttack() + "!");
                mainStage.sizeToScene();
                mainStage.show();
            });
        }

        private String nextAttack() {
            return attacks[random.nextInt(attacks.length)];
        }
    }

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

更新,2020 年 1 月

Java 9 添加了一个名为 的新特性Platform.startup(),您可以使用它来触发 JavaFX 运行时的启动,而无需定义派生自Application并调用launch()它的类。 Platform.startup()对方法有类似的限制launch()(您不能Platform.startup()多次调用),因此如何应用它的元素类似于launch()此答案中的讨论和 Wumpus 示例。

有关如何使用的演示,请参阅 Fabian 对如何实现 JavaFX 和非 JavaFX 交互Platform.startup()的回答?

于 2014-06-20T05:33:19.530 回答
4

我使用类似的东西,类似于其他答案。

private static volatile boolean javaFxLaunched = false;

public static void myLaunch(Class<? extends Application> applicationClass) {
    if (!javaFxLaunched) { // First time
        Platform.setImplicitExit(false);
        new Thread(()->Application.launch(applicationClass)).start();
        javaFxLaunched = true;
    } else { // Next times
        Platform.runLater(()->{
            try {
                Application application = applicationClass.newInstance();
                Stage primaryStage = new Stage();
                application.start(primaryStage);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }
}
于 2020-05-13T09:50:45.020 回答
3

试试这个,我试过这个,发现成功

@Override
public void start() {
    super.start();
    try {
                    // Because we need to init the JavaFX toolkit - which usually Application.launch does
                    // I'm not sure if this way of launching has any effect on anything
        new JFXPanel();

        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                // Your class that extends Application
                new ArtisanArmourerInterface().start(new Stage());
            }
        });
    } catch (Exception e) {
        e.printStackTrace();
    }
}
于 2017-03-13T13:11:40.017 回答