在JavaFX webview中加载一个新页面
Load a new page in JavaFX webview
我目前正在开发一个Java应用程序,该应用程序使用JavaFX webview来显示其UI(使用HTML/CSS)。
一切都很好,但我在系统中加载新页面时遇到麻烦。当我这样做时,Java和新页面的JavaScript之间的通信似乎被破坏了。
下面是我的代码:**浏览器**
public 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(some_url);
JSObject jsobj = (JSObject) webEngine.executeScript("window");
Bridge bridge = Bridge.getInstance();
bridge.init(webEngine);
jsobj.setMember("java", bridge);
//add the web view to the scene
getChildren().add(browser);
}
}
** Bridge **
public class Bridge {
private static Bridge instance = null;
private WebEngine webEngine;
public Bridge () {
}
public static Bridge getInstance() {
if(instance == null){
instance = new Bridge();
}
return instance;
}
public void init(WebEngine webEngine) {
if(this.webEngine == null) {
this.webEngine = webEngine;
}
}
public void btnStartSessionOnClick(String sessionName, String speakerNickname) {
// Load the new page
webEngine.load(some_other_url);
}
}
每当web引擎加载一个新页面时,它都会替换DOM,因此有一个不同的window
对象。您定义的jsobj
只设置一次,因此当加载新页面时,它将指向错误的对象。您需要在每次页面加载时重置此对象,您可以通过观察引擎的加载状态来完成。
你的设计对我来说不是很有意义:对我来说,把window
(jsobj
)对象作为Bridge
类的一部分而不是应用程序类的一部分更有意义。因为Browser
不是一个单例,它没有意义,使Bridge
成为一个单例(如果你有多个web视图在你的应用程序,例如?)。
这是一个SSCCE:
package application;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewTest extends Application {
@Override
public void start(Stage primaryStage) {
WebView webView = new WebView();
WebEngine engine = webView.getEngine();
Label output = new Label();
Bridge bridge = new Bridge(engine);
engine.load(getClass().getResource("/resources/First.html").toExternalForm());
Button first = new Button("Load First");
first.setOnAction(e -> engine.load(getClass().getResource("/resources/First.html").toExternalForm()));
Button second = new Button("Load Second");
second.setOnAction(e -> engine.load(getClass().getResource("/resources/Second.html").toExternalForm()));
TextField textField = new TextField();
Button button = new Button("Send");
EventHandler<ActionEvent> handler = e -> {
bridge.execute(result -> output.setText(result.toString()),
"showText", textField.getText());
textField.setText("");
};
button.setOnAction(handler);
textField.setOnAction(handler);
HBox controls = new HBox(5, first, second, textField, button, new Label("Web page says: "), output);
controls.setPadding(new Insets(10));
BorderPane root = new BorderPane(webView, null, null, controls, null);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Bridge
类:
package application;
import java.util.function.Consumer;
import javafx.concurrent.Worker.State;
import javafx.scene.web.WebEngine;
import netscape.javascript.JSObject;
public class Bridge {
private JSObject window ;
public Bridge(WebEngine engine) {
engine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
window = (JSObject) engine.executeScript("window");
window.setMember("application", this);
}
});
}
public void execute(Consumer<Object> callback, String function, Object... args) {
callback.accept(window.call(function, args));
}
}
和一些简单的测试HTML文件,我在类路径根目录下的resources
文件夹中。
First.HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>First</title>
<script>
function showText(text) {
document.getElementById("text").innerHTML = text;
return text;
}
</script>
</head>
<body>
<p>This is the first page</p>
<a href="Second.html">Go to the second page</a>
<div id="text"></div>
</body>
</html>
和Second.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Second</title>
<script>
function showText(text) {
document.getElementById("text").innerHTML = text;
return text;
}
</script>
</head>
<body>
<p>This is the second page</p>
<a href="First.html">Go back to the first page</a>
<div id="text"></div>
</body>
</html>
相关文章:
- 使用 JQuery 打开一个新的 php 页面
- 在IE11中,点击next或back按钮,使用intro.js打开一个新页面
- 与node.js的get/post混淆,并试图创建一个新页面
- window.打开一个新页面,然后单击新页面中的链接 - JavaScript
- 加载另一个相同页面时,使用新数据激活第一个网页
- 在当前页面中加载一个新的谷歌地图,加载AJAX
- 打开一个新页面作为模式窗口
- 在javascript中使用dblclick事件打开一个新页面
- 在Rails中更改选择值时加载一个新页面
- 在JavaFX webview中加载一个新页面
- 在php中按下一个按钮打开一个新页面
- 如何在浏览器中从iframe中加载一个新页面?
- 自动加载一个新页面,只访问正文中的一个元素
- 在新窗口中打开一个新页面,打印并关闭它
- 在网站退出时打开一个新页面
- 如何从javascript函数在jQuery Mobile中打开一个新页面
- 为什么不开窗户?位置加载一个新页面
- 如何在jsp页面上每隔10秒包含一个新页面
- 为什么javascript: on webview会跳转到一个新页面?
- 我试图在表单提交到一个新页面后,根据用户选择的多个选项(Javascript.html)重定向表单