JavaFX使用JavaScript调用Java方法 [英] JavaFX invoking Java methods using JavaScript
问题描述
我的应用程序完全以Web文档形式(HTML,CSS和JavaScript)设置样式,我只使用JavaFX WebView将其作为普通资源加载。
My application is completely styled in a web document form (HTML, CSS & JavaScript), and I'm only using JavaFX WebView to load it as a normal resource.
我想使用JavaScript从我的一个类(Java代码)调用一个方法。
I would like to invoke a method from one of my classes (a Java code) using JavaScript.
例如,一个简单的Hello World到控制台:
Like for example, a simple Hello World to the console:
public class Hello {
public void world() {
System.out.println("Hello World!");
}
}
如何调用在这种情况下,world()
方法?
所以我的页面代码是这样的:
So my code from the page is something like this:
<!-- onlick action from a button calls hello() function -->
<button onclick="hello();" value="Invoke"></button>
<script>
function hello() {
/* CODE WHICH INVOKE A JAVA METHOD */
}
</script>
有什么方法可以达到这个目的吗?
Any way to achieve this?
注意:对于那些正在寻找的人关于如何实现这一目标的完整而简单的示例,您可以测试下面写的所有以下代码。
Notice: For those people who were looking for a complete and simple example about how to achieve this, you can test all the following codes written below.
我终于实现了我的目标,感谢先生@Oshan_Mendis的回答。此示例基于Oracle docs的本教程: 6 Making Upcalls从JavaScript到JavaFX 。
I've finally achieved my goal, thanks to sir @Oshan_Mendis' answer. This example is based from this tutorial from Oracle docs: 6 Making Upcalls from JavaScript to JavaFX.
但是在这里,我将使用自己的代码,主要目标是使用JavaScript从Java代码调用方法HTML页面。
But here, I'll be using my own code, the main goal is to call a method from Java code using JavaScript from the HTML page.
Controller.java /* Controller class for WebView */
Hello.java /* Class in which method(s) will be invoked */
Main.java /* Main class (launches the application) */
main.fxml /* Main layout (WebView) */
index.html /* Main layout web page content */
1。创建Main-Class(Main.java)
1. Creating the Main-Class (Main.java)
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage stage) throws Exception {
/* The root layout of the application, an FXML contains the WebView layout. */
Parent root = FXMLLoader.load(Main.class.getResource("/main.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
2。准备主布局(main.fxml)
2. Preparing the Main layout (main.fxml)
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.web.WebView?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/8"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="Controller" <!-- The controller class for this layout -->
prefHeight="400.0"
prefWidth="300.0">
<children>
<!-- Given the webView ID to initiate the web page -->
<WebView fx:id="webView" />
</children>
</VBox>
3。设置网页(Controller.java)
3. Setting up the web page (Controller.java)
import java.net.URL;
import java.util.ResourceBundle;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker.State;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import netscape.javascript.JSObject;
public class Controller implements Initializable {
private WebEngine webEngine;
@FXML private WebView webView;
@Override
public void initialize(URL location, ResourceBundle resources) {
/* Load the web page URL (location of the resource) */
URL url = Controller.class.getResource("/index.html");
webEngine = webView.getEngine();
webEngine.load(url.toExternalForm());
/* Set the State listener as well as the name of the JavaScript object and its
* corresponding Java object (the class in which methods will be invoked) that
* will serve as the bridge for the two objects.
*/
webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends State> observableValue, State oldState, State newState) {
if (newState == State.SUCCEEDED) {
JSObject window = (JSObject) webEngine.executeScript("window");
/* The two objects are named using the setMember() method. */
window.setMember("invoke", new Hello());
}
}
});
}
}
4。首选类及其调用方法(Hello.java)
4. Preferred class and its method to invoke (Hello.java)
public class Hello {
public void world() {
System.out.println("Hello World!");
}
}
5。主要布局网页内容(index.html)
5. Main layout web page content (index.html)
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script>
function helloWorld() {
/* JavaScript object name and the method to invoke */
invoke.world();
}
</script>
</head>
<body>
<!-- onlick event calls helloWorld() function -->
<button onclick="helloWorld()">INVOKE</button>
</body>
</html>
注意:你可以执行其他鼠标在这种情况下除onclick事件之外的相关事件如:onmouseenter,onmouseover,onmousemove,onmouseup等。但我不确定这些是否是唯一支持调用方法的事件。
Note: You can perform other mouse-related events other than onclick event in this case like: onmouseenter, onmouseover, onmousemove, onmouseup, etc.. But I'm not really sure if these are the only supported events of invoking methods.
推荐答案
Java API文档 从JavaScript回调Java
public class JavaApplication {
public void exit() {
Platform.exit();
}
}
...
JavaApplication javaApp = new JavaApplication();
JSObject window = (JSObject) webEngine.executeScript("window");
window.setMember("app", javaApp);
然后,您可以从HTML页面引用对象和方法:
You can then refer to the object and the method from your HTML page:
<a href="" onclick="app.exit()">Click here to exit application</a>
这篇关于JavaFX使用JavaScript调用Java方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!