1. 程式人生 > >JavaFX的WebView中通過JavaScript回撥Java的程式

JavaFX的WebView中通過JavaScript回撥Java的程式

               

解決webview首次載入的html頁面無法使用js呼叫java程式問題。

根據官網給出的例子,自己寫了個總是呼叫不成功。以下是官網例子程式碼:

http://docs.oracle.com/javase/8/javafx/embedded-browser-tutorial/js-javafx.htm

import javafx.application.Application;import
javafx.application.Platform;import javafx.beans.value.ObservableValue;import javafx.concurrent.Worker.State;import javafx.event.ActionEvent;import javafx.geometry.HPos;import javafx.geometry.Pos;import javafx.geometry.VPos;import javafx.scene.Node;import javafx.scene.Scene;import javafx.scene.control.Button;import
javafx.scene.control.Hyperlink;import javafx.scene.image.Image;import javafx.scene.image.ImageView;import javafx.scene.layout.HBox;import javafx.scene.layout.Priority;import javafx.scene.layout.Region;import javafx.scene.paint.Color;import javafx.scene.web.WebEngine;import javafx.scene.web.WebView;import
javafx.stage.Stage;import netscape.javascript.JSObject; public class WebViewSample extends Application {     private Scene scene;     @Override    public void start(Stage stage) {        // create scene        stage.setTitle("Web View Sample");        scene = new Scene(new Browser(stage), 900, 600, Color.web("#666970"));        stage.setScene(scene);        // apply CSS style        scene.getStylesheets().add("webviewsample/BrowserToolbar.css");        // show stage        stage.show();    }     public static void main(String[] args) {        launch(args);    }} class Browser extends Region {     private final HBox toolBar;    final private static String[] imageFiles = new String[]{        "product.png",        "blog.png",        "documentation.png",        "partners.png",        "help.png"    };    final private static String[] captions = new String[]{        "Products",        "Blogs",        "Documentation",        "Partners",        "Help"    };    final private static String[] urls = new String[]{        "http://www.oracle.com/products/index.html",        "http://blogs.oracle.com/",        "http://docs.oracle.com/javase/index.html",        "http://www.oracle.com/partners/index.html",        WebViewSample.class.getResource("help.html").toExternalForm()    };    final ImageView selectedImage = new ImageView();    final Hyperlink[] hpls = new Hyperlink[captions.length];    final Image[] images = new Image[imageFiles.length];    final WebView browser = new WebView();    final WebEngine webEngine = browser.getEngine();    final Button toggleHelpTopics = new Button("Toggle Help Topics");    private boolean needDocumentationButton = false;            public Browser(final Stage stage) {        //apply the styles        getStyleClass().add("browser");                        for (int i = 0; i < captions.length; i++) {            // create hyperlinks            Hyperlink hpl = hpls[i] = new Hyperlink(captions[i]);            Image image = images[i]                    = new Image(getClass().getResourceAsStream(imageFiles[i]));            hpl.setGraphic(new ImageView(image));            final String url = urls[i];            final boolean addButton = (hpl.getText().equals("Help"));                          // process event             hpl.setOnAction((ActionEvent e) -> {                needDocumentationButton = addButton;                webEngine.load(url);            });                            }         // create the toolbar        toolBar = new HBox();        toolBar.setAlignment(Pos.CENTER);        toolBar.getStyleClass().add("browser-toolbar");        toolBar.getChildren().addAll(hpls);        toolBar.getChildren().add(createSpacer());         //set action for the button        toggleHelpTopics.setOnAction((ActionEvent t) -> {            webEngine.executeScript("toggle_visibility('help_topics')");        });          // process page loading        webEngine.getLoadWorker().stateProperty().addListener(            (ObservableValue<? extends State> ov, State oldState,                 State newState) -> {                    toolBar.getChildren().remove(toggleHelpTopics);                    if (newState == State.SUCCEEDED) {                        JSObject win                                = (JSObject) webEngine.executeScript("window");                        win.setMember("app", new JavaApp());                        if (needDocumentationButton) {                            toolBar.getChildren().add(toggleHelpTopics);                        }                    }        });         // load the home page                webEngine.load("http://www.oracle.com/products/index.html");         //add components        getChildren().add(toolBar);        getChildren().add(browser);    }        // JavaScript interface object    public class JavaApp {         public void exit() {            Platform.exit();        }    }     private Node createSpacer() {        Region spacer = new Region();        HBox.setHgrow(spacer, Priority.ALWAYS);        return spacer;    }     @Override    protected void layoutChildren() {        double w = getWidth();        double h = getHeight();        double tbHeight = toolBar.prefHeight(w);        layoutInArea(browser,0,0,w,h-tbHeight,0,HPos.CENTER,VPos.CENTER);        layoutInArea(toolBar,0,h-tbHeight,w,tbHeight,0,HPos.CENTER,VPos.CENTER);    }     @Override    protected double computePrefWidth(double height) {        return 900;    }     @Override    protected double computePrefHeight(double width) {        return 600;    }}


Example 5-1 help.html file

<html lang="en">    <head>        <!-- Visibility toggle script -->        <script type="text/javascript">            <!--            function toggle_visibility(id) {                var e = document.getElementById(id);                if (e.style.display == 'block')                    e.style.display = 'none';                else                    e.style.display = 'block';            }//-->        </script>    </head>    <body>        <h1>Online Help</h1>        <p class="boxtitle"><a href="#" onclick="toggle_visibility('help_topics');"   class="boxtitle">[+] Show/Hide Help Topics</a></p>            <ul id="help_topics" style='display:none;'>            <li>Products - Extensive overview of Oracle hardware and software products,                 and summary Oracle consulting, support, and educational services. </li>            <li>Blogs - Oracle blogging community (use the Hide All and Show All buttons                 to collapse and expand the list of topics).</li>            <li>Documentation - Landing page to start learning Java. The page contains                 links to the Java tutorials, developer guides, and API documentation.</li>            <li>Partners - Oracle partner solutions and programs. Popular resources and                 membership opportunities.</li>        </ul>        <p><a href="about:blank" onclick="openAppUtil.exit()">Exit the Application</a></p>    </body></html>



弄了幾個小時,最後懷疑是不是javafx版本問題,我的版本和官網給的例子不一致導致的。

於是我就把官網的例子程式碼拷貝下來,直接使用它的例子,居然成功了。看來是程式哪裡出問題了。

接下來就是不停的對照程式碼,希望能發現問題所在。又是2個多小時過去了,終於找到問題所在了,原來要右鍵點選重新載入一次頁面,js才能呼叫java程式。

好奇怪的現象!!!官網例子不用重新載入是因為進入help.html頁面是通過點選工具欄上的help按鈕,瀏覽器才載入進去的,瀏覽器首次載入的是Oracle首頁。

如果把官網例子

webEngine.load("http://www.oracle.com/products/index.html");

改為

webEngine.load(WebViewSample.class.getResource("help.html").toExternalForm());

那麼一樣也會出現點選超連結後不會退出程式,而是會進入一個空白頁面,然後需要滑鼠右擊選擇退回,再次點選超連結才能退出程式。

也就是說help.html頁面要第二次載入js中才能呼叫java程式。

下面是我寫的例子的解決方案。

package application.view;import application.Main;import application.util.ConfigUtil;import application.util.OpenAppUtil;import javafx.beans.value.ChangeListener;import javafx.beans.value.ObservableValue;import javafx.concurrent.Worker;import javafx.concurrent.Worker.State;import javafx.fxml.FXML;import javafx.scene.web.WebEngine;import javafx.scene.web.WebView;import netscape.javascript.JSObject;/** * 根面板控制器 * @author pelin */public class RootLayoutController @FXML WebView browser;  WebEngine webEngine; /**     * 初始化,類似與建構函式. fxml載入完成後自動呼叫該方法     */    @FXML    private void initialize() {     webEngine = browser.getEngine();     OpenAppUtil openAppUtil = new OpenAppUtil();     webEngine.getLoadWorker().stateProperty().addListener(                new ChangeListener<State>() {                  @Override public void changed(ObservableValue ov, State oldState, State newState) {                      if (newState == Worker.State.SUCCEEDED) {//                        stage.setTitle(webEngine.getLocation());//                       System.out.println(newState);                       JSObject win = (JSObject) webEngine.executeScript("window");                    win.setMember("openAppUtil", openAppUtil);                      }                      else if (newState == Worker.State.FAILED){//                       System.out.println(newState);//                       webEngine.load(HtmlPath.class.getResource("home.html").toExternalForm());                      }                      else{//                       System.out.println(newState);                      }                    }                });//     webEngine.load(ConfigUtil.getValue("homePage"));     webEngine.load(Main.class.getResource("view/test.html").toExternalForm());//     webEngine.load("http://10.100.1.240:8089/test.html");         }    }

主要修改的地方是:

win.setMember("openAppUtil", new OpenAppUtil());

改為

win.setMember("openAppUtil", openAppUtil);

並且在webEngine.getLoadWorker().stateProperty().addListener之前建立openAppUtil物件。即:OpenAppUtil openAppUtil = new OpenAppUtil();

這樣webview在首次載入html後就可以呼叫java程式了。








           

再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智慧的隊伍中來!https://blog.csdn.net/jiangjunshow