1
votes

I want to add the hovered Hyperlink from a WebView and display it in a corner.

How can i achieve? It should be like Chromes feature:

Example-Chrome-Screenshot

enter image description here

Example WebView Code with many links:

import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.ScrollPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class core extends Application {
    @Override
    public void start(final Stage stage) {
        Scene scene = new Scene(new Group());

        final WebView browser = new WebView();
        final WebEngine webEngine = browser.getEngine();

        ScrollPane scrollPane = new ScrollPane();
        scrollPane.setContent(browser);

        webEngine.load("http://java2s.com");

        scene.setRoot(scrollPane);

        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
2

2 Answers

3
votes

First thing - your Scene should contain more than one element, not only the ScrollPane. You need a TextField to show hyperlinks' content and these two Controls should be placed on some kind of a Pane. To handle displaying the content when your mouse goes over the hyperlink, you need to get all the nodes, which are of a hyperlink type, and then add proper listeners to them.

Look at the code below, it does what you would like to achieve (it's partially based on the 'JavaFX WebView addHyperlinkListener' article from the 'Inspiration and Expression' blog):

public class Main extends Application {

  @Override
  public void start(final Stage stage) {
    Scene scene = new Scene(new Group());

    final WebView browser = new WebView();
    final WebEngine webEngine = browser.getEngine();

    ScrollPane scrollPane = new ScrollPane();
    scrollPane.setContent(browser);

    TextField textField = new TextField();
    textField.setVisible(false);
    textField.setEditable(false);

    webEngine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
      if (newValue == Worker.State.SUCCEEDED) {

        EventListener mouseOverEventListener = new EventListener() {
          @Override
          public void handleEvent(Event ev) {
            String href = ((Element) ev.getTarget()).getAttribute("href");
            textField.setText(href);
            textField.setVisible(true);
            textField.setPrefWidth(textField.getText().length() * 6); //
            System.out.println(href);
          }
        };

        EventListener mouseOutEventListener = new EventListener() {
          @Override
          public void handleEvent(Event ev) {
            textField.setVisible(false);
          }
        };

        Document document = webEngine.getDocument();
        NodeList nodeList = document.getElementsByTagName("a");
        for (int i = 0 ; i < nodeList.getLength() ; i++) {
          ((EventTarget) nodeList.item(i)).addEventListener("mouseover",mouseOverEventListener,false);
          ((EventTarget) nodeList.item(i)).addEventListener("mouseout",mouseOutEventListener,false);
        }
      }
    });

    String content = "http://java2s.com";
    webEngine.load(content);

    AnchorPane anchorPane = new AnchorPane();
    anchorPane.getChildren().add(scrollPane);
    anchorPane.getChildren().add(textField);
    AnchorPane.setBottomAnchor(textField, 0.0);
    AnchorPane.setLeftAnchor(textField, 0.0);

    scene.setRoot(anchorPane);
    stage.setScene(scene);
    stage.show();
  }

  public static void main(String[] args) {
    launch(args);
  }
}
1
votes

My complete example of how to display links from all elements:

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.html.HTMLIFrameElement;
import org.w3c.dom.Element;
import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class getWeblinksInCorner extends Application {

    EventListener mouseOverEventListener;
    EventListener mouseOutEventListener;

    @Override
    public void start(final Stage stage) {
        final WebView browser = new WebView();
        Label textField = new Label();

        final WebEngine webEngine = browser.getEngine();

        textField.setVisible(false);

        webEngine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue == Worker.State.SUCCEEDED) {

                mouseOverEventListener = new EventListener() {
                    @Override
                    public void handleEvent(Event ev) {
                        String href = getNextHref((Element) ev.getTarget());
                        if (href != null && !href.isEmpty()) {
                            if (href.startsWith("/")) {
                                href = ((Element) ev.getTarget()).getBaseURI() + href;
                            }
                            textField.setText(href + "   ");
                            textField.setPrefHeight(22);
                            textField.setMaxWidth(650);
                            textField.setStyle("-fx-border-color: #C6C6C7; -fx-background-color: #F2F2F2;");
                            textField.setVisible(true);
                        }
                    }

                    private String getNextHref(Element target) {
                        while (target.getAttribute("href") == null) {
                            if (target.toString().contains("HTMLHtmlElement")) {
                                return "";
                            }
                            target = (Element) target.getParentNode();
                            if (target == null) {
                                return "";
                            }
                        }
                        return target.getAttribute("href");
                    }
                };

                mouseOutEventListener = new EventListener() {

                    @Override
                    public void handleEvent(Event ev) {
                        textField.setVisible(false);
                    }
                };

                Document document = webEngine.getDocument();
                addListener(document.getElementsByTagName("*"));
            }
        });

        String content = "http://java2s.com";
        webEngine.load(content);

        TextField tf = new TextField();
        tf.textProperty().bind(webEngine.locationProperty());
        BorderPane pane = new BorderPane();

        AnchorPane ap = new AnchorPane(browser, textField);
        AnchorPane.setBottomAnchor(browser, 0.0);
        AnchorPane.setLeftAnchor(browser, 0.0);
        AnchorPane.setTopAnchor(browser, 0.0);
        AnchorPane.setRightAnchor(browser, 0.0);
        AnchorPane.setBottomAnchor(textField, 0.0);
        AnchorPane.setLeftAnchor(textField, 0.0);
        pane.setCenter(ap);
        pane.setTop(tf);

        Scene scene = new Scene(pane);
        stage.setScene(scene);
        stage.show();
    }

    private void addListener(NodeList nodeList) {
        for (int i = 0; i < nodeList.getLength(); i++) {
            try {
                HTMLIFrameElement iFrame = ((HTMLIFrameElement) nodeList.item(i));
                addListener(iFrame.getContentDocument().getElementsByTagName("*"));
            } catch (Exception e) {
                Element el = (Element) nodeList.item(i);
                while (!el.toString().contains("HTMLHtmlElement")) {
                    el = (Element) el.getParentNode();
                    ((EventTarget) el).removeEventListener("mouseover", mouseOverEventListener, false);
                    ((EventTarget) el).removeEventListener("mouseout", mouseOutEventListener, false);
                }
                ((EventTarget) nodeList.item(i)).addEventListener("mouseover", mouseOverEventListener, false);
                ((EventTarget) nodeList.item(i)).addEventListener("mouseout", mouseOutEventListener, false);
            }
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}