Вызов Java-метода из JavaScript
Для вызова Java-метода JavaApp#test()
из JavaScript наиболее важная часть реализации уже включена в ваш второй фрагмент кода.По-прежнему отсутствует только сам вызов, например,
<button onclick='app.test();'>Call JavaApp#test-method</button>
Однако необходимо учитывать две важные вещи: во-первых, вложенный класс JavaApp
должен быть public
.Во-вторых, приложение должно содержать ссылку на JavaApp
-экземпляр, необходимый для обратного вызова из JavaScript для выполнения метода (см. здесь , раздел Calling back to Java from JavaScript
).
Таким образом, вы должны изменить свой код следующим образом:
JavaApp javaApp = new JavaApp(); // Hold a reference...
webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
public void changed(ObservableValue<? extends State> o, State old, final State state) {
if (state == State.SUCCEEDED) {
JSObject win = (JSObject) webView.getEngine().executeScript("window");
win.setMember("app", javaApp); // Use the reference...
}
}
});
и
public class JavaApp { // Change the access modifier from private to public...
public void test() {
Platform.exit();
}
}
Вызов JavaScript-метода из Java
Если вы хотите вызвать метод JavaScript из Java, например, test()
, это делается с помощью
webView.getEngine().executeScript("test()");
В качестве примера я использую test()
-метод, указанный в вашем третьем фрагмент, где, однако, имя должно быть изменено с app.test()
на test()
.Если вызывается webView.getEngine().executeScript("test()");
, выполняется test()
, за исключением метода alert()
.Это связано с тем, что для некоторых JavaScript-методов (например, window.alert()
) WebEngine
перенаправляет запрос на обратный вызов (onAlert
в случае window.alert()
).Если обратный вызов не определен, запрос игнорируется (см. здесь , раздел Обратные вызовы интерфейса пользователя ).Например, обратный вызов для alert()
может быть определен следующим образом:
webView.getEngine().setOnAlert(event -> showAlert(event.getData()));
, где showAlert(String msg)
- это собственный метод, а msg
содержит исходное сообщение (done
в случае вашего * 1061).* -method), например:
private void showAlert(String msg){
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Custom Alert");
alert.setHeaderText("");
alert.setContentText(msg);
alert.showAndWait();
}
Больше примеров можно найти в Как сделать, чтобы веб-браузер JavaFX отображал предупреждение и подтверждающее сообщение .
РЕДАКТИРОВАТЬ:
Пример кода для вызова Java-метода из JavaScript: при нажатии кнопки вызывается Java-метод JavaApp#test()
из JavaScript, который выводит текст done
в текстовой области.
import javafx.application.Application;
import javafx.concurrent.Worker.State;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class WebViewExecuteJavaFromJavaScript extends Application {
private TextArea textArea;
private static String HTML_STRING = "" +
"<!DOCTYPE html>\r\n" +
"<html>\r\n" +
" <head>\r\n" +
" </head>\r\n" +
" <body>" +
" <button onclick='app.test();'>Call Java-method JavaApp#test()...</button>" + // Call Java-method JavaApp#test()...
" </body>\r\n" +
"</html>";
@Override
public void start(final Stage stage) {
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.setJavaScriptEnabled(true);
webEngine.loadContent(HTML_STRING);
JavaApp javaApp = new JavaApp();
webEngine.getLoadWorker().stateProperty().addListener((o, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
JSObject win = (JSObject) webView.getEngine().executeScript("window");
win.setMember("app", javaApp); // Enable call of Java-method from JavaScript...
}
});
textArea = new TextArea();
textArea.setWrapText(true);
VBox root = new VBox();
root.setPadding(new Insets(5));
root.setSpacing(5);
root.getChildren().addAll(webView, textArea);
Scene scene = new Scene(root);
stage.setTitle("Demo: Execute Java from JavaScript");
stage.setScene(scene);
stage.setWidth(450);
stage.setHeight(300);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
public class JavaApp {
public void test() {
textArea.setText(textArea.getText() + "done ");
}
}
}
Пример кода для вызова JavaScript-метода из Java: при нажатии кнопки вызывается JavaScript-метод test()
из Java, который выводит текст done
в текстовой области и в диалоговом окне.
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewExecuteJavaScriptFromJava extends Application {
private static String HTML_STRING = "" +
"<!DOCTYPE html>\r\n" +
"<html>\r\n" +
" <head>\r\n" +
" </head>\r\n" +
" <body>" +
" <textarea id=\"textarea\" name=\"textarea\" cols=55 rows=3 wrap=\"virtual\"></textarea>" +
" <script language=\"javascript\">\r\n" +
" function test() {\r\n" +
" textarea.value+='done '; \r\n" +
" alert('done');\r\n" + // Is ignored as long as no callback is defined...
" }\r\n" +
" </script>" +
" </body>\r\n" +
"</html>";
@Override
public void start(final Stage stage) {
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
webEngine.setJavaScriptEnabled(true);
webEngine.loadContent(HTML_STRING);
webEngine.setOnAlert(event -> showAlert(event.getData())); // Define callback for JavaScript-alert...
Button button = new Button("Call JavaScript-method test()...");
button.setOnAction(event -> webView.getEngine().executeScript("test()")); // Call JavaScript-method test()...
VBox root = new VBox();
root.setPadding(new Insets(5));
root.setSpacing(5);
root.getChildren().addAll(button, webView);
Scene scene = new Scene(root);
stage.setTitle("Demo: Execute JavaScript from Java");
stage.setScene(scene);
stage.setWidth(450);
stage.setHeight(300);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
private void showAlert(String msg){
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Custom Alert");
alert.setHeaderText("");
alert.setContentText(msg);
alert.showAndWait();
}
}