JavaFX WebView – 获取“复制链接到剪贴板”功能

huangapple go评论143阅读模式
英文:

JavaFX WebView - Get "Copy Link to Clipboard"-function

问题

I want to get the URL of a link of a website in WebView. By default you can use the default ContextMenu and right click on the link and select "Copy Link to Clipboard". But I have a custom ContextMenu, so I can't use that. Is there a way to access that method or another way of getting the URL of the link that is right-clicked?

So far I have an ActionListener that refers to the MenuItem and not the link.

public void createContextMenu() {
   ContextMenu contextMenu = new ContextMenu();

   MenuItem menuItem_download = new MenuItem("Download");
   contextMenu.getItems().add(menuItem_download);

   menuItem_download.setOnAction(e -> fileDownloadContextMenu(e));

   webView.setOnMousePressed(e -> {
      if (e.getButton() == MouseButton.SECONDARY) {
         contextMenu.show(webView, e.getScreenX(), e.getScreenY());
      } else{
         contextMenu hide();
      }
   });
}
public void fileDownloadContextMenu(Event e) {

   System.out.println(e.getSource());
   
   // Code for downloading
}

Thank you.

EDIT:
I tried this for the concatenated String:

private final String getHrefJs = "var elt = document.elementFromPoint(%f, %f);\n" +
         "var href = \"\";\n" +
         "if (elt.tagName.toLowerCase() == \"a\"){\n" +
         "href = elt.getAttribute(\"href\");}\n" +
         "href\n";

EDIT 2:
For debugging I did this:

private void showMenuIfNeeded(double x, double y) throws URISyntaxException {

   String js = String.format(getHrefJs, x, y);
   Object href = engine.executeScript(js);
   System.out.println(js);

   if (href == null) {
      System.out.println("null");
   } else {
      System.out.println("not null:");
      System.out.println(href.getClass());
      System.out.println(href.toString().isEmpty());
   }

   if (href != null && href.toString().length() > 0) {
      System.out.println("checkup");
      link = new URI(engine.getLocation()).resolve(href.toString()).toString();
      contextMenu.show(webView, Side.TOP, x, y);
   }
}

The console output looks like this:

var elt = document.elementFromPoint(53,000000, 150,000000);
var href = "";
if (elt.tagName.toLowerCase() == "a"){
href = elt.getAttribute("href");}
href

not null:
class java.lang.String
true

So somehow "href" is not null but empty, and therefore the following if-statement is not executed. That is why the ContextMenu is not showing. But I don't know why "href" is empty.

英文:

I want to get the URL of a link of a website in WebView. By default you can use the default ContextMenu and right click on the link and select "Copy Link to Clipboard". But I have a custom ContextMenu, so I can't use that. Is there a way to access that method or another way of getting the URL of the link that is right-clicked?
So far I have an ActionListener that refers to the MenuItem and not the link.

   public void createContextMenu() {
      ContextMenu contextMenu = new ContextMenu();

      MenuItem menuItem_download = new MenuItem("Download");
      contextMenu.getItems().add(menuItem_download);

      menuItem_download.setOnAction(e -> fileDownloadContextMenu(e));

      webView.setOnMousePressed(e -> {
         if (e.getButton() == MouseButton.SECONDARY) {
            contextMenu.show(webView, e.getScreenX(), e.getScreenY());
         } else{
            contextMenu.hide();
         }
      });
   }
   public void fileDownloadContextMenu(Event e) {

      System.out.println(e.getSource());
      
      // Code for downloading
   }

Thank you.

EDIT:
I tried this for the concatenated String:

   private final String getHrefJs = "var elt = document.elementFromPoint(%f, %f);\n" +
            "var href = \"\";\n" +
            "if (elt.tagName.toLowerCase() == \"a\"){\n" +
            "href = elt.getAttribute(\"href\");}\n" +
            "href\n";

EDIT 2:
For debugging I did this:

private void showMenuIfNeeded(double x, double y) throws URISyntaxException {

      String js = String.format(getHrefJs, x, y);
      Object href = engine.executeScript(js);
      System.out.println(js);

      if (href == null) {
         System.out.println("null");
      } else {
         System.out.println("not null:");
         System.out.println(href.getClass());
         System.out.println(href.toString().isEmpty());
      }


      if (href != null && href.toString().length() > 0) {
         System.out.println("checkup");
         link = new URI(engine.getLocation()).resolve(href.toString()).toString();
         contextMenu.show(webView, Side.TOP, x, y);
      }
   }

The console output looks like this:

var elt = document.elementFromPoint(53,000000, 150,000000);
var href = "";
if (elt.tagName.toLowerCase() == "a"){
href = elt.getAttribute("href");}
href

not null:
class java.lang.String
true

So somehow "href" is not null but empty and therefore the following if-statement is not executed. That is why the ContextMenu ist not showing. But I don't know why "href" is empty.

答案1

得分: 2

你可以使用一些JavaScript来在右键单击A标签时检索链接。然后,只需使用一些标准的JavaFX来将其复制到剪贴板。

JavaScript策略只是查找鼠标坐标处的HTML元素,检查其标签名称,然后从中检索href属性,如果它是一个锚点。

可能有更简单的方法来实现这一点,但这似乎有效。

import javafx.application.Application;
import javafx.geometry.Side;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

import java.net.URI;
import java.net.URISyntaxException;

public class HelloApplication extends Application {

    private String link;
    private WebView webView;
    private WebEngine engine;
    private ContextMenu contextMenu;

    private final String getHrefJs = """
                var elt = document.elementFromPoint(%f, %f);
                var href = "";
                if (elt.tagName.toLowerCase() == "a") {
                    href = elt.getAttribute("href");
                }
                href
        """;

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

    @Override
    public void start(Stage stage) {
        webView = new WebView();
        webView.setContextMenuEnabled(false);
        engine = webView.getEngine();
        engine.load("https://repo.maven.apache.org/maven2/");

        MenuItem copyLink = new MenuItem("Copy link address");
        Label linkLabel = new Label();
        copyLink.setOnAction(e -> {
            linkLabel.setText(link);
            Clipboard clipboard = Clipboard.getSystemClipboard();
            ClipboardContent content = new ClipboardContent();
            content.putString(link);
            clipboard.setContent(content);
        });

        contextMenu = new ContextMenu(copyLink);

        webView.setOnContextMenuRequested(e -> {
            try {
                showMenuIfNeeded(e.getX(), e.getY());
            } catch (URISyntaxException ex) {
                throw new RuntimeException(ex);
            }
        });

        BorderPane root = new BorderPane(webView);
        root.setTop(linkLabel);
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    private void showMenuIfNeeded(double x, double y) throws URISyntaxException {

        String js = String.format(getHrefJs, x, y);
        Object href = engine.executeScript(js);

        if (href != null && href.toString().length() > 0) {
            link = new URI(engine.getLocation()).resolve(href.toString()).toString();
            contextMenu.show(webView, Side.TOP, x, y);
        }
    }
}
英文:

You can use some Javascript to retrieve the link if the right-click is over an A tag. Then just use some standard JavaFX to copy it to the clipboard.

The Javascript strategy is just to lookup the HTML element at the mouse coordinates, check its tagname and then retrieve the href attribute from it if it is an anchor.

There may be easier ways to achieve this, but this seems to work.

import javafx.application.Application;
import javafx.geometry.Side;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import java.net.URI;
import java.net.URISyntaxException;
public class HelloApplication extends Application {
private String link;
private WebView webView;
private WebEngine engine;
private ContextMenu contextMenu;
private final String getHrefJs = """
var elt = document.elementFromPoint(%f, %f);
var href = "";
if (elt.tagName.toLowerCase() == "a") {
href = elt.getAttribute("href");
}
href
""";
public static void main(String[] args) {
launch();
}
@Override
public void start(Stage stage) {
webView = new WebView();
webView.setContextMenuEnabled(false);
engine = webView.getEngine();
engine.load("https://repo.maven.apache.org/maven2/");
MenuItem copyLink = new MenuItem("Copy link address");
Label linkLabel = new Label();
copyLink.setOnAction(e -> {
linkLabel.setText(link);
Clipboard clipboard = Clipboard.getSystemClipboard();
ClipboardContent content = new ClipboardContent();
content.putString(link);
clipboard.setContent(content);
});
contextMenu = new ContextMenu(copyLink);
webView.setOnContextMenuRequested(e -> {
try {
showMenuIfNeeded(e.getX(), e.getY());
} catch (URISyntaxException ex) {
throw new RuntimeException(ex);
}
});
BorderPane root = new BorderPane(webView);
root.setTop(linkLabel);
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
private void showMenuIfNeeded(double x, double y) throws URISyntaxException {
String js = String.format(getHrefJs, x, y);
Object href = engine.executeScript(js);
if (href != null && href.toString().length() > 0) {
link = new URI(engine.getLocation()).resolve(href.toString()).toString();
contextMenu.show(webView, Side.TOP, x, y);
}
}
}

huangapple
  • 本文由 发表于 2023年3月20日 23:28:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/75792212.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定