In my JavaFX project, I have a listener on a WebView's WebEngine that waits for a website to fully render. Then I need to access the resulted DOM Document. This does not work if I don't know to which WebEngine the listener belongs!
Creating a variable or simply using the webView
that exists is not an option! This is because I'm creating several webViews with ChangeListeners.
How can I assign them to each other now?
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()
}
}
});
UPDATE
Here is a minimal working example for the problem I'm facing: https://github.com/mg98/StackOverflow-Demonstration
It is basically about: 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]);
}
}
}
Controller.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;
}
}
sample.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>