[英]Customized context menu on javafx webview/webengine
How may I have a customized context menu for whole entry of the document in WebEngine
javafx? 如何在
WebEngine
javafx中为文档的整个条目提供自定义上下文菜单?
Something like this 像这样的东西
+------------+
|Reload |
|Save page |
|Hide Images |
+------------+
I like to invoke and show this context popup for whole document entry(same for every node). 我喜欢调用并显示整个文档条目的上下文弹出窗口(每个节点都相同)。 Thanks.
谢谢。
I don't see a way to interact with the default context menu. 我没有看到与默认上下文菜单交互的方法。 However, it's not hard to disable it and implement your own.
但是,禁用它并实现自己的并不困难。
Disable the default context menu with 使用默认上下文菜单禁用
webView.setContextMenuEnabled();
Then create your own context menu, and register a mouse listener with the web view to show it on right click: 然后创建自己的上下文菜单,并使用Web视图注册鼠标侦听器以在右键单击时显示它:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
public class WebViewContextMenuTest extends Application {
private final String START_URL =
"http://stackoverflow.com/questions/27047447/customized-context-menu-on-javafx-webview-webengine/27047830#27047830";
@Override
public void start(Stage primaryStage) {
TextField locationField = new TextField(START_URL);
WebView webView = new WebView();
webView.getEngine().load(START_URL);
webView.setContextMenuEnabled(false);
createContextMenu(webView);
locationField.setOnAction(e -> {
webView.getEngine().load(getUrl(locationField.getText()));
});
BorderPane root = new BorderPane(webView, locationField, null, null, null);
primaryStage.setScene(new Scene(root, 800, 600));
primaryStage.show();
}
private void createContextMenu(WebView webView) {
ContextMenu contextMenu = new ContextMenu();
MenuItem reload = new MenuItem("Reload");
reload.setOnAction(e -> webView.getEngine().reload());
MenuItem savePage = new MenuItem("Save Page");
savePage.setOnAction(e -> System.out.println("Save page..."));
MenuItem hideImages = new MenuItem("Hide Images");
hideImages.setOnAction(e -> System.out.println("Hide Images..."));
contextMenu.getItems().addAll(reload, savePage, hideImages);
webView.setOnMousePressed(e -> {
if (e.getButton() == MouseButton.SECONDARY) {
contextMenu.show(webView, e.getScreenX(), e.getScreenY());
} else {
contextMenu.hide();
}
});
}
private String getUrl(String text) {
if (text.indexOf("://")==-1) {
return "http://" + text ;
} else {
return text ;
}
}
public static void main(String[] args) {
launch(args);
}
}
There's no easy solution for this, since there's no public API, and a request is still unresolved. 对此没有简单的解决方案,因为没有公共API,并且请求仍未解决。
The hacky solution uses some private API, so it's not very advisable since it could change without notice. hacky解决方案使用了一些私有API,所以它不太合适,因为它可能会在没有通知的情况下发生变化。
The ContextMenu
shown when the user right clicks on the web page is in another window, so using some lookups we'll try to find it, then access to its content and then modify existing or add more MenuItem
s. 当用户右键单击网页时显示的
ContextMenu
在另一个窗口中,因此使用一些查找我们将尝试找到它,然后访问其内容然后修改现有或添加更多MenuItem
。
These are the private classes required: 这些是所需的私人课程:
import com.sun.javafx.scene.control.skin.ContextMenuContent;
import com.sun.javafx.scene.control.skin.ContextMenuContent.MenuItemContainer;
In our application, we listen for a context menu request: 在我们的应用程序中,我们监听上下文菜单请求:
@Override
public void start(Stage primaryStage) {
WebView webView = new WebView();
WebEngine webEngine = webView.getEngine();
Scene scene = new Scene(webView);
primaryStage.setScene(scene);
primaryStage.show();
webView.setOnContextMenuRequested(new EventHandler<ContextMenuEvent>() {
@Override
public void handle(ContextMenuEvent e) {
getPopupWindow();
}
});
}
where getPopupWindow()
will: getPopupWindow()
将在哪里:
ContextMenu
ContextMenu
实例 context-menu
. context-menu
。 This is a node having as its only child a ContextMenuContent
instance. ContextMenuContent
实例。 VBox
as a container for all the items, which are MenuItem
in an special container, MenuItemContainer
. VBox
为所有的项目,这是一个容器MenuItem
中的一个特殊的容器, MenuItemContainer
。 Customize the items as you need to: 根据需要自定义项目:
private PopupWindow getPopupWindow() {
@SuppressWarnings("deprecation")
final Iterator<Window> windows = Window.impl_getWindows();
while (windows.hasNext()) {
final Window window = windows.next();
if (window instanceof ContextMenu) {
if(window.getScene()!=null && window.getScene().getRoot()!=null){
Parent root = window.getScene().getRoot();
// access to context menu content
if(root.getChildrenUnmodifiable().size()>0){
Node popup = root.getChildrenUnmodifiable().get(0);
if(popup.lookup(".context-menu")!=null){
Node bridge = popup.lookup(".context-menu");
ContextMenuContent cmc= (ContextMenuContent)((Parent)bridge).getChildrenUnmodifiable().get(0);
VBox itemsContainer = cmc.getItemsContainer();
for(Node n: itemsContainer.getChildren()){
MenuItemContainer item=(MenuItemContainer)n;
// customize text:
item.getItem().setText("My Custom: "+item.getItem().getText());
// customize graphic:
item.getItem().setGraphic(new ImageView(new Image(getClass().getResource("unlock24.png").toExternalForm())));
}
// remove some item:
// itemsContainer.getChildren().remove(0);
// adding new item:
MenuItem menuItem = new MenuItem("Save page");
menuItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
System.out.println("Save Page");
}
});
// add new item:
cmc.getItemsContainer().getChildren().add(cmc.new MenuItemContainer(menuItem));
return (PopupWindow)window;
}
}
}
return null;
}
}
return null;
}
This is how it looks like: 这是它的样子:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.