尝试在 JavaFX WebView DOM 和控制 class 之间同步状态
Trying to synchronize states between JavaFX WebView DOM and controlling class
在我的控制器 class 中,我设置了一个 WebView 对象
@FXML
private WebView newsletterPreview;
// some stuff...
urlString = url.toExternalForm();
WebEngine engine = newsletterPreview.getEngine();
bridge = new JSBridge(engine, this);
JSBridge 代码片段 ...
private String headlineCandidate;
public String getHeadlineCandidate() {
return headlineCandidate;
}
//mo stuff...
public JSBridge(WebEngine engine, ENewsLetterDialogController controller) {
engine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
window = (JSObject) engine.executeScript("window");
window.setMember("bridge", this);
engine.executeScript(loadDomListenerScript());
}
});
}
private String loadDomListenerScript() {
return WOWResourceUtils.resourceToString(LISTENER_SCRIPT);
}
public void captureHeadline(String element) {
this.headlineCandidate = element;
System.out.println(headlineCandidate);
}
侦听器脚本片段..
//listener script
"use strict";
document.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement, text = target.textContent ||
text.innerText;
window.bridge.captureHeadline(target.parentElement.outerHTML);
});
其中 LISTENER_SCRIPT 作为资源嵌入 Javascript,headlineCandidate 是一个 public 字符串 属性
我有以下工作:
我导航加载网页,我可以让 JSBridge class 回显我单击的任何元素的预期父元素 html(显然这是为了测试)。但是,我找不到将该信息返回给应用程序线程的好方法,因此我可以(例如)在用户单击正确的 HTML 元素时启用按钮。是的,这种设计是基于对页面的某些假设。这是用例的一部分。
根本问题似乎是 WebView 与应用程序在不同的线程上,但我找不到同步两者的好方法
我应该尝试从应用程序线程进行轮询吗?
对不起,如果之前有人问过,在这里搜索了大约 3 天
使用 Platform.runLater 将数据从非 JavaFX 线程传送到 JavaFX 线程:
// Java method invoked as a result of a callback from a
// JavaScript event handler in a webpage.
public void callbackJava(String data) {
// We are currently not on the JavaFX application thread and
// should not directly update the scene graph.
// Instead we call Platform.runLater to ship processing of data
// to the JavaFX application thread.
Platform.runLater(() -> handle(data));
}
public void handle(String data) {
// now we are on the JavaFX application thread and can
// update the scene graph.
label.setText(data);
}
在我的控制器 class 中,我设置了一个 WebView 对象
@FXML
private WebView newsletterPreview;
// some stuff...
urlString = url.toExternalForm();
WebEngine engine = newsletterPreview.getEngine();
bridge = new JSBridge(engine, this);
JSBridge 代码片段 ...
private String headlineCandidate;
public String getHeadlineCandidate() {
return headlineCandidate;
}
//mo stuff...
public JSBridge(WebEngine engine, ENewsLetterDialogController controller) {
engine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> {
if (newState == State.SUCCEEDED) {
window = (JSObject) engine.executeScript("window");
window.setMember("bridge", this);
engine.executeScript(loadDomListenerScript());
}
});
}
private String loadDomListenerScript() {
return WOWResourceUtils.resourceToString(LISTENER_SCRIPT);
}
public void captureHeadline(String element) {
this.headlineCandidate = element;
System.out.println(headlineCandidate);
}
侦听器脚本片段..
//listener script
"use strict";
document.addEventListener('click', function(e) {
e = e || window.event;
var target = e.target || e.srcElement, text = target.textContent ||
text.innerText;
window.bridge.captureHeadline(target.parentElement.outerHTML);
});
其中 LISTENER_SCRIPT 作为资源嵌入 Javascript,headlineCandidate 是一个 public 字符串 属性
我有以下工作:
我导航加载网页,我可以让 JSBridge class 回显我单击的任何元素的预期父元素 html(显然这是为了测试)。但是,我找不到将该信息返回给应用程序线程的好方法,因此我可以(例如)在用户单击正确的 HTML 元素时启用按钮。是的,这种设计是基于对页面的某些假设。这是用例的一部分。
根本问题似乎是 WebView 与应用程序在不同的线程上,但我找不到同步两者的好方法
我应该尝试从应用程序线程进行轮询吗?
对不起,如果之前有人问过,在这里搜索了大约 3 天
使用 Platform.runLater 将数据从非 JavaFX 线程传送到 JavaFX 线程:
// Java method invoked as a result of a callback from a
// JavaScript event handler in a webpage.
public void callbackJava(String data) {
// We are currently not on the JavaFX application thread and
// should not directly update the scene graph.
// Instead we call Platform.runLater to ship processing of data
// to the JavaFX application thread.
Platform.runLater(() -> handle(data));
}
public void handle(String data) {
// now we are on the JavaFX application thread and can
// update the scene graph.
label.setText(data);
}