簡體   English   中英

來自JavaScript的JavaFX WebView up調用不起作用

[英]JavaFX WebView up call from JavaScript doesn't work

我有一個JavaFX WebView,並希望從webview中顯示的“test.html”調用類“JavaBridge”的方法“hello”。 為什么這不起作用? 我確保只有在完全呈現頁面時才將“bridge”對象添加到window.object中,這可能不是問題所在。 我也看不到HTML的任何問題。

這是HTML代碼(“test.html”):

<html>
<head>
</head>
<body>
    <a href="#click" onclick="bridge.hello()">call java</a>
</body>
</html>

這是Java代碼:

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import netscape.javascript.JSObject;

public class HelloWorld extends Application {

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

  @Override
  public void start(Stage primaryStage) {

    java.net.URI uri = java.nio.file.Paths.get("test.html").toAbsolutePath().toUri();
    WebView root = new javafx.scene.web.WebView();
    root.getEngine().load(uri.toString());

    root.getEngine().
    getLoadWorker().
    stateProperty().
    addListener(new ChangeListener < State > () {
      @Override public void changed(ObservableValue ov, State oldState, State newState) {

        if (newState == Worker.State.SUCCEEDED) {
          System.out.println("READY");
          JSObject jsobj = (JSObject) root.getEngine().executeScript("window");
          jsobj.setMember("bridge", new JavaBridge());
        }

      }
    });
    primaryStage.setScene(new javafx.scene.Scene(root, 800, 600));
    primaryStage.show();
  }
}

class JavaBridge {
  public void hello() {
    System.out.println("hello");
  }
}

你的內部類應該在主類中。 它應該是公開的。 像這樣:

import java.net.URL;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;

public class HelloWorld extends Application {

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

    @Override
    public void start(Stage primaryStage) {

        final URL url = getClass().getResource("test.html");

        WebView root = new javafx.scene.web.WebView();
        root.getEngine().load(url.toExternalForm());

        root.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
            @Override
            public void changed(ObservableValue ov, State oldState, State newState) {

                if (newState == Worker.State.SUCCEEDED) {
                    System.out.println("READY");
                    JSObject jsobj = (JSObject) root.getEngine().executeScript("window");
                    jsobj.setMember("bridge", new JavaBridge());
                }

            }
        });
        primaryStage.setScene(new javafx.scene.Scene(root, 800, 600));
        primaryStage.show();
    }

    public class JavaBridge {
        public void hello() {
            System.out.println("hello");
        }
    }
}

在Java 10.0.2上使用此橋接功能時,我注意到它不能始終如一地工作。 Javascript upcalls一直沒有運行。

經過研究,我發現了與Java垃圾收集器相關的OpenJDK錯誤,這似乎也發生在普通的JDK上: https//bugs.openjdk.java.net/browse/JDK-8170085

實際上,根據https://docs.oracle.com/javase/9​​/docs/api/javafx/scene/web/WebEngine.html ,建議將橋存儲到變量中以避免Java GC收集對象。

在向類中添加私有變量之后,JS到Java調用開始在我的應用程序中一直工作。

我有同樣的問題,修復它的唯一方法是將Bridge存儲在靜態變量上。 這是使用javafx FileChooser的示例。

public class Controller implements Initializable {
    @FXML private WebView webview;
    @FXML private JFXButton btn_insertimg;
    @FXML private AnchorPane anchorpane;
    private WebEngine webEngine;
    public static Bridge bridge; //it's important to be static

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        webEngine = webview.getEngine();
        webEngine.getLoadWorker().stateProperty().addListener(
                (ov, oldState, newState) -> {
                    if (newState == Worker.State.SUCCEEDED) {
                        //todo when the document is fully loaded
                        FileChooser fileChooser=new FileChooser();
                        bridge=new Bridge(webview,fileChooser);
                        JSObject window = (JSObject) webEngine.executeScript("window");
                        window.setMember("myFileChooser", bridge);
                        System.out.println("member "+window.getMember("myFileChooser").toString());;
                    }//end of SUCCEEDED state
                });

        webEngine.load(getClass().getResource("/patient/texteditor/summernote.html").toExternalForm());
    }
    public class Bridge{
        FileChooser fileChooser;
        WebView webView;
        Bridge(WebView webView,FileChooser fileChooser){
            this.webView=webView;
            this.fileChooser=fileChooser;
        }
        public void display(){
            fileChooser.showOpenDialog(webView.getScene().getWindow());
        }
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM