英文:
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);
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论