【问题标题】:JavaFX HTMLEditor HyperlinksJavaFX HTMLEditor 超链接
【发布时间】:2016-08-18 22:18:55
【问题描述】:
我正在尝试使用格式化输入进行聊天,我的问题是默认情况下您无法将链接放入 JavaFX HTMLEditor,因此我添加了一个用超链接替换所选文本的按钮。
我的问题是 1:编辑器中的超链接是可点击的,如果单击它会导致编辑器打开链接,问题编号 2:当我单击 webView 中的链接时,它不会在外部浏览器中打开,而是在内部webView 本身,所以它实际上是相同的问题,因为 HTMLEditor 正在使用 webView。
有谁知道如何“解决”这个问题?
【问题讨论】:
标签:
java
html
javafx
webview
hyperlink
【解决方案1】:
由于 JavaFX 中的 WebView 在下面使用 java.net.URLConnection,您可以使用其内置机制来提供您的自定义处理程序,该处理程序将创建一个连接,该连接将 url 委托给将在默认浏览器中打开 url 的操作系统。这是一个例子:
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import javafx.application.Application;
import javafx.application.HostServices;
import javafx.scene.Scene;
import javafx.scene.web.HTMLEditor;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class HTMLEditorSample extends Application {
@Override
public void start(Stage stage) {
stage.setTitle("HTMLEditor Sample");
stage.setWidth(400);
stage.setHeight(300);
final HTMLEditor htmlEditor = new HTMLEditor();
htmlEditor.setPrefHeight(245);
Scene scene = new Scene(htmlEditor);
stage.setScene(scene);
stage.show();
URL.setURLStreamHandlerFactory(protocol -> {
if (protocol.startsWith("http")) {
return new CustomUrlHandler();
}
return null;
});
WebView webview = (WebView) htmlEditor.lookup(".web-view");
webview.getEngine().load("http://google.com");
}
public static void main(String[] args) {
launch(args);
}
public class CustomUrlHandler extends URLStreamHandler {
@Override
protected URLConnection openConnection(URL u) throws IOException {
return new HostServicesUrlConnection(u, getHostServices());
}
}
public class HostServicesUrlConnection extends HttpURLConnection {
private URL urlToOpen;
private HostServices hostServices;
protected HostServicesUrlConnection(URL u, HostServices hostServices) {
super(u);
this.urlToOpen= u;
this.hostServices = hostServices;
}
@Override
public void disconnect() {
// do nothing
}
@Override
public boolean usingProxy() {
return false;
}
@Override
public void connect() throws IOException {
hostServices.showDocument(urlToOpen.toExternalForm());
}
@Override
public InputStream getInputStream() throws IOException {
return new InputStream() {
@Override
public int read() throws IOException {
return 0;
}
};
}
}
}
更新:
之前的解决方案将覆盖所有其他使用 URLConnection 的类的功能,这可能不是您想要的。通过使用负载工人的位置和状态,我找到了一个更简单的解决方案。请注意,取消没有 Platform.runLater 的 load worker 会导致 JDK 版本 8u66 上的 JVM 崩溃:
webview.getEngine().getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
@Override
public void changed(ObservableValue<? extends State> observable, State oldValue, State newValue) {
Platform.runLater(() -> {
webview.getEngine().getLoadWorker().cancel();
});
}
});
webview.getEngine().locationProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
getHostServices().showDocument(newValue);
}
});