3

Java の WebView で開くか、外部ブラウザで手動で開くページを作成しています。ページが Java から読み込まれる場合 - 特定のコールバックを実行するために必要です。Java は一種のバックエンドとして使用されますが、ページが手動で読み込まれる場合は、そのリソースから別のデータを読み込む必要があります。だから私は、ドキュメントの読み込み時に呼び出すことができる JS の「JavaInit」オブジェクトを登録しようとしています。HTML は次のようになります。

<html>
    <head>
        <script type='text/javascript' src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
        <script type="text/javascript">

            DefaultInit = {
                init: function(x) {
                    return "Default init: " + x;
                }
            };

            $(function() {

                var text;
                if (window["JavaInit"] && JavaInit.init)
                    text = JavaInit.init("passed text");
                else
                    text = DefaultInit.init("passed text");

                $("#title").html(text);
            });

        </script>
    </head>
    <body>
        <h1 id="title"></h1>
    </body>
</html>

ここでページonloadイベントの前に JS メンバーを設定する際の問題について読んだことがあります。

public class Test extends Application {

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

    @Override
    public void start(Stage primaryStage) throws Exception {
        WebView web = new WebView();
        Scene scene = new Scene(web, 400, 300);
        primaryStage.setScene(scene);
        primaryStage.show();
        initWeb(web);
    }

    private static void initWeb(WebView web) {

        WebEngine eng = web.getEngine();
        ((JSObject)eng.executeScript("window")).setMember("JavaInit", new JavaInit());

        URL url = Test.class.getResource("/test.html");
        eng.load(url.toString());
    }

    public static class JavaInit {

        public String init(Object o) {
            return "Java init: " + o;
        }
    }
}

そして、それは必要に応じて正確に機能しますが、誰かが「ページの再読み込み」を呼び出す前に 1 回だけです。エンジンをリロードすると、「ウィンドウ」オブジェクトが再作成されたように見え、登録されているすべてのメンバーが消えます。

「状態プロパティ」リスナー内に #setMember を配置できます。

private static void initWeb(WebView web) {

    WebEngine eng = web.getEngine();

    eng.getLoadWorker().stateProperty().addListener((val, oldState, newState) -> {
        if (newState == State.SUCCEEDED)
            ((JSObject)eng.executeScript("window")).setMember("JavaInit", new JavaInit());
    });

    URL url = Test.class.getResource("/test.html");
    eng.load(url.toString());
}

ただし、window.onload が起動された後にのみ呼び出され、デフォルトの init が常に呼び出されます。これは、最小限の遅延で init コードを呼び出すことで修正できます。

$(function() {

    setTimeout(function() {
        var text;
        if (window["JavaInit"] && JavaInit.init)
            text = JavaInit.init("passed text");
        else
            text = DefaultInit.init("passed text");

        $("#title").html(text);
    });
});

次に、コントロールが JS から Java (存在する場合) に処理され、登録された関数に戻り、programm は毎回正常に動作します。

しかし、Java がすべてのメンバーを正常に登録することを期待して init delay を作成するのは、ちょっと間違っているようです。この種の機能を実現するための「より適切な」方法を知っている人はいますか? また、本番環境では時間がかかり、メンバーが登録される前にJSが遅延関数を呼び出す可能性はありますか? または、WebEngine が Java イベントと JS 実行を継続的に処理するという保証はありますか?

ありがとう!

4

1 に答える 1

1

同じ問題があり、onload イベントが JS で発生する前にメンバーを設定する必要があります。ヘッダーの JS にアラートを追加しました。

    alert("command:inject");

そしてJavaコードでは:

    webEngine.setOnAlert(new EventHandler<WebEvent<String>>() {
        @Override
        public void handle(WebEvent<String> event) {
            // set members here
        }
    });

オン アラート ハンドルが同期的に実行されているように見えるため、onload が起動したときに開始されるスクリプトは、アラート ハンドラーに設定されたメンバーを確認します。

于 2016-01-06T09:52:19.443 に答える