Reputation: 397
I want to learn more about JavaFX and so I tried to set up Webview. I copied the webview example from the Oracle website and added Upcall functionality. But it isn't working. Actually I have no idea how to debug a website in Webview. So here is the java code:
package boersensim;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
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 Main extends Application {
private Scene scene;
@Override public void start(Stage stage) {
// create the scene
stage.setTitle("Web View");
scene = new Scene(new Browser(),750,500, Color.web("#666970"));
stage.setScene(scene);
//scene.getStylesheets().add("webviewsample/BrowserToolbar.css");
stage.show();
}
public static void main(String[] args){
launch(args);
}
}
class Browser extends Region {
final WebView browser = new WebView();
final WebEngine webEngine = browser.getEngine();
public Browser() {
//apply the styles
getStyleClass().add("browser");
// load the web page
webEngine.load("test.html");
//add the web view to the scene
getChildren().add(browser);
JSObject jsobj = (JSObject) webEngine.executeScript("window");
jsobj.setMember("java", new Bridge());
}
private Node createSpacer() {
Region spacer = new Region();
HBox.setHgrow(spacer, Priority.ALWAYS);
return spacer;
}
@Override protected void layoutChildren() {
double w = getWidth();
double h = getHeight();
layoutInArea(browser,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
}
@Override protected double computePrefWidth(double height) {
return 750;
}
@Override protected double computePrefHeight(double width) {
return 500;
}
}
class Bridge {
public void exit() {
//Platform.exit();
System.out.print("Hello!UPCALL");
}
}
The corrosponding HTML is:
Click<a href="#" onclick="java.exit();">here</a>to exit the application
When I click the link nothing happens.
Thanks to you in advance, Daniel
Upvotes: 2
Views: 2330
Reputation: 145
Three things to be change in you code Daniel,
1) Make your class Bridge public
2) Enable JavaScript like this webEngine.setJavaScriptEnabled(true);
3) set Member Bridge() on page loaded event like bellow
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
@Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
// TODO Auto-generated method stub
if (newValue == Worker.State.SUCCEEDED) {
JSObject jso = (JSObject) webEngine.executeScript("window");
jso.setMember("java", new Bridge());
}
}
});
Welcome, Daniel
Upvotes: 0
Reputation: 756
I also followed this tutorial (probably the one you used): https://blogs.oracle.com/javafx/entry/communicating_between_javascript_and_javafx
And found that it makes the JVM crash. So I reported an issue on the JavaFX jira, and I got the following reply:
It is a requirement since 7u5 that the methods called from JS be accessible in Java sense, i.e. >public members of public classes. (This is mentioned in the last comment to the article). In this >particular test case Bridge should be declared a public class.
The crash was fixed in JDK8. Now an exception is thrown.
And that works.
Upvotes: 2
Reputation: 31
set Bridge() on page loaded event
webEngine.setJavaScriptEnabled(true);
webEngine.getLoadWorker().stateProperty().addListener(
new ChangeListener<Worker.State>() {
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
JSObject jso = (JSObject) webEngine.executeScript("window");
jso.setMember("java", new Bridge());
}
}
});
Upvotes: 3