首页 > 解决方案 > 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>

标签: javajavafx

解决方案


使用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]);
    }
}

推荐阅读