java - JavaFX WebEngine:我需要我的 ChangeListener 知道它的触发器 WebEngine
问题描述
在我的 JavaFX 项目中,我在 WebView 的 WebEngine 上有一个监听器,它等待网站完全呈现。然后我需要访问生成的 DOM 文档。如果我不知道侦听器属于哪个 WebEngine,这将不起作用!
创建变量或仅使用webView
存在的变量不是一种选择!这是因为我正在使用 ChangeListeners 创建几个 webView。我现在如何将它们分配给彼此?
webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
// Here I do my stuff
// I need to access webView.getEngine().getDocument()
}
}
});
更新
这是我面临的问题的最小工作示例:https ://github.com/mg98/StackOverflow-Demonstration
它基本上是关于: Main.java
package sample;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.w3c.dom.Document;
public class Main extends Application {
private static Controller ctrl;
private final static String[] urls = new String[] {
"https://google.com",
"https://youtube.com",
"https://facebook.com",
"https://twitter.com",
"https://stackoverflow.com"
};
@Override
public void start(Stage primaryStage) throws Exception{
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("sample.fxml"));
Parent root = fxmlLoader.load();
ctrl = fxmlLoader.getController();
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
findSomething();
}
public static void main(String[] args) {
launch(args);
}
private void findSomething() {
for (int i = 0; i < 5; i++) {
System.out.println("Request to " + urls[i]);
WebView webView = ctrl.createWebView();
webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>() {
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState) {
if (newState == Worker.State.SUCCEEDED) {
// The BIG QUESTION is: What is the corresponding WebEngine to call?
Document doc = webView.getEngine().getDocument();
// As you will see, the responses print in totally random order
System.out.println(doc.getElementsByTagName("title").item(0).getTextContent());
}
}
});
webView.getEngine().load(urls[i]);
}
}
}
控制器.java
package sample;
import javafx.fxml.FXML;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;
public class Controller {
@FXML
private VBox browsers;
@FXML
protected void initialize() {
}
WebView createWebView() {
WebView webView = new WebView();
browsers.getChildren().add(webView);
return webView;
}
}
示例.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<GridPane alignment="center" hgap="10" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/9" fx:controller="sample.Controller">
<columnConstraints>
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
</rowConstraints>
<children>
<VBox fx:id="browsers" prefHeight="200.0" prefWidth="100.0" />
</children>
</GridPane>
解决方案
使用WebView
setUserData
和 switch 语句来跟上不同站点上发生的变化。如果您单击站点上的其中一个链接,它将告诉您哪个WebView
处理了该链接。
private void findSomething()
{
for (int i = 0; i < 5; i++) {
System.out.println("Request to " + urls[i]);
WebView webView = ctrl.createWebView();
webView.setUserData(urls[i]);
webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<Worker.State>()
{
@Override
public void changed(ObservableValue ov, Worker.State oldState, Worker.State newState)
{
if (newState == Worker.State.SUCCEEDED) {
// The BIG QUESTION is: What is the corresponding WebEngine to call?
Document doc = webView.getEngine().getDocument();
String userData = webView.getUserData().toString();
switch (userData) {
case "https://google.com":
System.out.println(doc.getElementsByTagName("title").item(0).getTextContent());
System.out.println("Do something with the google site");
System.out.println("");
break;
case "https://youtube.com":
System.out.println(doc.getElementsByTagName("title").item(0).getTextContent());
System.out.println("Do something with the youtube site");
break;
case "https://facebook.com":
System.out.println(doc.getElementsByTagName("title").item(0).getTextContent());
System.out.println("Do something with the facebook site");
break;
case "https://twitter.com":
System.out.println(doc.getElementsByTagName("title").item(0).getTextContent());
System.out.println("Do something with the twitter site");
break;
case "https://stackoverflow.com":
System.out.println(doc.getElementsByTagName("title").item(0).getTextContent());
System.out.println("Do something with the stackoverflow site");
break;
}
// As you will see, the responses print in totally random order
}
}
});
webView.getEngine().load(urls[i]);
}
}
推荐阅读
- python - Python 正则表达式 sub()
- oracle - 从 apex_item.text 获取价值
- android - 如何获取 firebase 数据库元素的推送 ID 以便在 listView 中显示它
- sql - 从循环输出 Oracle SQL 创建表
- generics - 如何在不使该函数泛型的情况下将带有泛型的闭包传递给函数?
- android - Android VIewGroup 句柄触摸,子句柄点击
- ignite - Apache Ignite 如何对空间数据进行分区?
- javascript - 访问花括号AngularJS中的窗口高度?
- ssh - Nifi ExecuteProcess 处理器中的错误 - 主机密钥验证失败
- excel - 在 Excel 2016 中加快 VBA 搜索