web-dev-qa-db-ja.com

java)でlaunch()を複数回呼び出す方法

Javaでlaunch()を複数回呼び出す方法「ERRORIN MAIN:Java.lang.IllegalStateException:アプリケーションの起動を複数回呼び出すことはできません」という例外が表示されます。

Javaアプリケーションでリクエストが来るとjavafxを呼び出し、webview操作の完了後にwebviewを開き、Platform.exit()メソッドを使用してjavafxウィンドウを閉じます。2番目のリクエストが来るとこれを取得します。エラーこのエラーをsloveする方法。

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);
13
venu

JavaFXアプリケーションで launch() を複数回呼び出すことはできません。これは許可されていません。

Javadocから:

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

ウィンドウを定期的に表示するための提案

  1. Application.launch()を1回呼び出すだけです。
  2. Platform.setImplicitExit(false) を使用してJavaFXランタイムをバックグラウンドで実行し続け、最後のアプリケーションウィンドウを非表示にしたときにJavaFXが自動的にシャットダウンしないようにします。
  3. 次に別のウィンドウが必要になったときは、ウィンドウをラップします show() 呼び出しを Platform.runLater() にして、JavaFXアプリケーションで呼び出しが実行されるようにします。糸。

Swingをミキシングする場合は、 Application の代わりに JFXPanel を使用できますが、使用パターンは上記のパターンと同様になります。

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() という新機能を追加しました。これを使用すると、Applicationから派生したクラスを定義してlaunch()その上。 Platform.startup()にはlaunch()メソッドと同様の制限があるため(Platform.startup()を複数回呼び出すことはできません)、適用方法の要素はlaunch()この回答のディスカッションとWumpusの例。

Platform.startup()の使用方法のデモンストレーションについては、 JavaFXと非JavaFXの相互作用を実現する方法 に対するFabianの回答を参照してください。

25
jewelsea

これを試してみて、私はこれを試して成功しました

@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();
    }
}
3
I B