I have an application in JavaFX where I use a WebView to display a particular web page.
I need that the right mouse button on the page doesn't work; but if I use it on HTML elements that have id=eventDiv, it is supposed to work on them. It's JavaFX 17.
I set ContexMenuEnabled false and I don't have context menu and that's OK.
WebView webView = new WebView();
webView.setContextMenuEnabled(false);
webView.getEngine().setJavaScriptEnabled(true);
WebEngine webEngine = webView.getEngine();
webEngine.setUserStyleSheetLocation("data:, body { background-color: #EBEBEB; }");
webEngine.setOnAlert(event -> showAlert(event.getData()));
webEngine.setConfirmHandler(message -> showConfirm(message));
System.out.println(url);
webEngine.load(url);
I did something like this using AI and documentation, but unfortunately it doesn't work. And I would like that when I right-click on a given HTML element, which in this case is a div in a table cell, it opens a custom context menu, which is done in JS. What can I do to make it work?
webView.setOnMousePressed(event -> {
if (event.isSecondaryButtonDown()) {
event.consume();
}
});
webView.getEngine()
.getLoadWorker()
.stateProperty()
.addListener((observable, oldValue, newValue) -> {
if (newValue == Worker.State.SUCCEEDED) {
JSObject window = (JSObject) webView.getEngine().executeScript("window");
window.setMember("eventDiv", new EventDivHandler());
}
});
public class EventDivHandler {
public void handleEventDivClick() {
// Obsłuż PPM na elemencie z id=eventDiv
System.out.println("Kliknięto na element z id=eventDiv");
}
}
From some testing, calling setContextMenuEnabled(false) appears to disable all context menu handling. Even JavaScript listeners no longer receive contextmenu events. I think the better way to disable the context menu used by WebView is via JavaScript:
window.oncontextmenu = e => e.preventDefault();
You can then add your own contextmenu event listeners to whichever elements you want to handle specially. These listeners would invoke the Java callback object.
For example:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
public class Main extends Application {
public static void main(String[] args) {
launch(Main.class, args);
}
// Keep a strong reference to the listener
private final ContextMenuListener listener = new ContextMenuListener();
@Override
public void start(Stage primaryStage) {
var view = new WebView();
var engine = view.getEngine();
var worker = engine.getLoadWorker();
// Disable context menu when loading page to prevent user from
// being able to show it before the script is executed.
view.contextMenuEnabledProperty().bind(worker.runningProperty().not());
// Run script when page is successfully loaded. There may be a way
// to do this earlier, not sure.
worker.stateProperty().addListener((obs, oldState, newState) -> {
switch (newState) {
default -> {}
case FAILED -> worker.getException().printStackTrace();
case SUCCEEDED -> installContextMenuListener(engine);
}
});
// Load HTML content (insert your own URL)
engine.load("<SOME URL>");
primaryStage.setScene(new Scene(view, 500, 300));
primaryStage.show();
}
private void installContextMenuListener(WebEngine engine) {
var window = (JSObject) engine.executeScript("window");
window.setMember("ctxMenuListener", listener);
engine.executeScript(
"""
window.oncontextmenu = e => e.preventDefault();
let eventDiv = document.querySelector("#eventDiv");
eventDiv.oncontextmenu = e => {
e.preventDefault();
ctxMenuListener.handle(eventDiv, e.screenX, e.screenY);
};
""");
}
public static class ContextMenuListener {
public void handle(JSObject source, double screenX, double screenY) {
System.out.printf("contextmenu(%s, %.2f, %.2f)%n", source, screenX, screenY);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With