5

WebView を多用する JavaFX アプリケーションがあります。JavaScript コードが使用できるオブジェクトを DOM に挿入しようとしていますが、新しいページが読み込まれるときにこれらのオブジェクトを使用できるようにする必要があります。

ただし、プログラムを実行すると、FirebugLite は DOM にオブジェクトを表示しますが、関数は実行されません。

一部の Oracle ドキュメントによると、これは JavaScript から Java へのアップコールを提供する適切な方法のようです。同じことを説明しているStackOverflow の投稿もいくつか見ました。

私は何が欠けていますか?Windows 7 で Java 8、Update 51、64 ビットを使用しています。

ジャワ:

public class DemoApplication extends Application {

    Debug debug;

    @Override
    public void start(final Stage stage) throws Exception {
        debug = new Debug();

        WebView browser = new WebView();
        WebEngine webEngine = browser.getEngine();
        webEngine.getLoadWorker().stateProperty().addListener(
                new ChangeListener<Worker.State>() {
                    @Override
                    public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
                        if (newValue == Worker.State.SUCCEEDED) {
                            JSObject windowObject = (JSObject) webEngine.executeScript("window");
                            windowObject.setMember("Debug", debug);
                        }
                    }
                }
        );
        webEngine.load("http://localhost:8080/page1.html");

        stage.setScene(new Scene(browser));
        stage.show();
    }

}

public class Debug {
    public void print(final Object text) {
        System.err.println(text);
    }
}

HTML/JavaScript:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title></title>
  <script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script>
  <script>
    Debug.print("Hello");
  </script>
</head>
<body>
  Page 1
  <a href="page2.html">Page 2</a>
</body>
</html>

Firebug スクリーンショット:

ここに画像の説明を入力

4

1 に答える 1

3

WebEngine がページをロードし、ChangeListener がさまざまな時点 (SCHEDULED、RUNNING、SUCCEEDED など) で呼び出されることが起こっていると思います。Worker.State.SUCCEEDED イベントが発生すると、ページはすべてのコンテンツの読み込みを完了し、そのコンテンツの実行も完了しています。したがって、基本的に、JavaScript コードでの Debug.print() への呼び出しは早い段階で発生し、未定義またはnullのオブジェクトを呼び出していました。

オブジェクトを追加したに Java 部分によって実行される JavaScript 関数を追加すると、すべてが期待どおりに機能するためです。

これは、JavaScript 側を変更した方法です。

<script>
  // callback that uses java objects
  window.ready = function() { 
    Debug.print("Hello");
  }
</script>

そして、これは私がJava側をどのように変更したかです:

webEngine.getLoadWorker().stateProperty().addListener(
    new ChangeListener<Worker.State>() {
        @Override
        public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) {
            if (newValue == Worker.State.SUCCEEDED) {
                JSObject windowObject = (JSObject) webEngine.executeScript("window");
                windowObject.setMember("Debug", debug); // insert object
                windowObject.call("ready"); // execute callback
            }
        }
    }
);

ここでの重要な変更点は、JavaScript の ready() 関数と、Java 側でオブジェクトを注入した後にその関数を呼び出すことです。これにより、これらのオブジェクトが呼び出される前に使用可能になります。

いくつかの異なるページでこれを試してみましたが、ページからページへ移動するときに、ready() 関数が呼び出されたときに、WebEngine.reload() または WebHistory.go() を使用している場合でも、Debug.print() が適切に実行されました。

于 2015-08-27T16:42:58.657 に答える