JavaFX WebView addHyperlinkListener
July 30th, 2013 | by Tonny Kohar |If you had use JTextPane HTML rendering mode, you can easily addHyperLinkListener to catch link click event and provide the handler. But there is no Hyperlink listener in JavaFX WebView.
So here how to do it in JavaFX WebView
* tested on Java 7u25
public class WebViewRenderer extends JFXPanel public static final String EVENT_TYPE_CLICK = "click"; public static final String EVENT_TYPE_MOUSEOVER = "mouseover"; public static final String EVENT_TYPE_MOUSEOUT = "mouseclick"; protected WebView webView; public WebViewRenderer() { ... Platform.runLater(new Runnable() { @Override public void run() { initFX(); } }); } private void initFX() { createScene(); webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() { @Override public void changed(ObservableValue ov, State oldState, State newState) { if (newState == Worker.State.SUCCEEDED) { EventListener listener = new EventListener() { @Override public void handleEvent(Event ev) { String domEventType = ev.getType(); //System.err.println("EventType: " + domEventType); if (domEventType.equals(EVENT_TYPE_CLICK)) { String href = ((Element)ev.getTarget()).getAttribute("href"); ////////////////////// // here do what you want with that clicked event // and the content of href ////////////////////// } } }; Document doc = webView.getEngine().getDocument(); NodeList nodeList = doc.getElementsByTagName("a"); for (int i = 0; i < nodeList.getLength(); i++) { ((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_CLICK, listener, false); //((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_MOUSEOVER, listener, false); //((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_MOUSEOVER, listener, false); } } } }); } } |
Thats it done. Now you can handle the hyperlink click event.
But if you really want to replicate addHyperlinkListener as in JTextPane just add the following
@Override public void addHyperlinkListener(HyperlinkListener listener) { listenerList.add(HyperlinkListener.class, listener); } @Override public void removeHyperlinkListener(HyperlinkListener listener) { listenerList.remove(HyperlinkListener.class, listener); } protected void fireHyperlinkUpdate(EventType eventType, String desc) { HyperlinkEvent event = new HyperlinkEvent(this, eventType, null, desc); // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == HyperlinkListener.class) { ((HyperlinkListener) listeners[i + 1]).hyperlinkUpdate(event); } } } |
And replace the above initFX with
protected void initFX() { createScene(); webView.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() { @Override public void changed(ObservableValue ov, State oldState, State newState) { if (newState == Worker.State.SUCCEEDED) { EventListener listener = new EventListener() { @Override public void handleEvent(Event ev) { String domEventType = ev.getType(); //System.err.println("EventType: " + domEventType); final EventType eventType; if (domEventType.equals(EVENT_TYPE_CLICK)) { eventType = HyperlinkEvent.EventType.ACTIVATED; } else if (domEventType.equals(EVENT_TYPE_MOUSEOVER)) { eventType = HyperlinkEvent.EventType.ENTERED; } else if (domEventType.equals(EVENT_TYPE_MOUSEOUT)) { eventType = HyperlinkEvent.EventType.EXITED; } else { return; } final String href = ((Element)ev.getTarget()).getAttribute("href"); if (href == null) { return; } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fireHyperlinkUpdate(eventType, href); } }); } }; Document doc = webView.getEngine().getDocument(); NodeList nodeList = doc.getElementsByTagName("a"); for (int i = 0; i < nodeList.getLength(); i++) { ((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_CLICK, listener, false); ((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_MOUSEOVER, listener, false); ((EventTarget) nodeList.item(i)).addEventListener(EVENT_TYPE_MOUSEOVER, listener, false); } } } }); } |
So now you can easily use something like
WebViewRenderer renderer = new WebViewRenderer(); renderer.addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent evt) { EventType eventType = evt.getEventType(); String href = evt.getDescription(); if (eventType.equals(HyperlinkEvent.EventType.ACTIVATED)) { // do something } else if (eventType.equals(HyperlinkEvent.EventType.ENTERED)) { // do something } else if (eventType.equals(HyperlinkEvent.EventType.EXITED)) { // do something } } }); |
4 Responses to “JavaFX WebView addHyperlinkListener”
By Adam on Sep 30, 2013 | Reply
I’m migrating to from JEditorPane to JavaFX and this is one of the things I’ve been looking for.
Would it be possible to see the entire source? I get what you’ve posted here but some things are unclear, such as the collection used for listenerList.
Many thanks.
By Adam on Sep 30, 2013 | Reply
😆 Oh nevermind. I was doing this in the wrong class and not the one that extended JFXPanel. Works really well. Please accept my thanks once more 🙂
By vinay on Feb 18, 2014 | Reply
thanks,really useful .Helped me alot.
By Aleksandar on Feb 21, 2014 | Reply
Hi. Is there any chance to see entire source? I have some problems with this. . .