[英]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.