14

javaでlaunch()を複数回呼び出す方法「メインエラー:java.lang.IllegalStateException:アプリケーションの起動を複数回呼び出すことはできません」という例外が発生します

リクエストが来たときにjavafxを呼び出し、webview操作が完了した後にwebviewを開いて、Platform.exit()メソッドを使用してjavafxウィンドウを閉じているときに、Javaアプリケーションで残りのクレイントを作成しました。2 番目のリクエストが来ると、このエラーが発生します。このエラーを再処理する方法を教えてください。

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 を混在させる場合は、 Applicationの代わりにJFXPanelを使用できますが、使用パターンは上で概説したものと似ています。

ウンパスのサンプル

この例は、タイマー タスクも含むため、必要以上に複雑です。ただし、完全なスタンドアロンの例が提供されているため、役立つ場合があります。

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を呼び出すことなく、JavaFX ランタイムの起動をトリガーできますlaunch()Platform.startup()メソッドには同様の制限があります (複数回launch()呼び出すことはできません)。そのため、適用方法の要素は、この回答の議論と Wumpus の例に似ています。Platform.startup()launch()

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

于 2014-06-20T05:33:19.530 に答える
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 に答える