JavaFX HTMLEditor超链接

时间:2016-04-25 13:28:54

标签: java html javafx webview hyperlink

我正在尝试使用格式化输入进行聊天,我的问题是您无法在默认情况下将链接放入JavaFX HTMLEditor,因此我添加了一个按钮,用超链接重新选择所选文本。 我的问题是1:编辑器中的超链接是可点击的,如果你点击它就会导致编辑器打开链接而问题2:当我点击webView中的链接时,它不会在外部浏览器中打开但是在里面因为HTMLEditor使用webView,所以它实际上是相同的问题。 有谁知道如何“修复”那个?

1 个答案:

答案 0 :(得分: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的情况下取消加载工作程序会导致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);
  }
});