简体   繁体   English

JavaFX:TabPane上下文菜单,取决于所选的选项卡

[英]JavaFX: TabPane context menu, depending on selected tab

I want to have a TabPane with multiple tabs, with a context menu different for every tab. 我想要一个带有多个选项卡的TabPane,每个选项卡都具有不同的上下文菜单。

Setting the ContextMenu on the TabPane obviously results in the same ContextMenu used regardless of selected tab. 在TabPane上设置ContextMenu显然会导致使用相同的ContextMenu,而与选定的选项卡无关。 I tried setting different ContextMenus on different Tabs, but this has two unwanted effects: 我尝试在不同的选项卡上设置不同的ContextMenus,但这有两个不利影响:

  1. The context menu is only opened when right-clicking on the tab header (whereas setting it on the TabPane allows right-clicking anywhere inside the tab). 仅在右键单击选项卡标题时才打开上下文菜单(而在TabPane上进行设置则允许右键单击选项卡内的任何位置)。 I want the user to be able to access the Context Menu from anywhere inside the tab, not just the header. 我希望用户能够从选项卡内的任何地方访问上下文菜单,而不仅仅是标题。

  2. Right-clicking on one tab header while another is selected still opens the context menu of the tab clicked on - I want the context menu to depend on the tab currently selected. 右键单击一个选项卡标题,同时选择另一个选项卡标题,仍会打开单击的选项卡的上下文菜单-我希望上下文菜单取决于当前选择的选项卡。

The only way I could think of how to do it is to catch onContextMenuRequested, see which tab is currently selected, and set various MenuItems visible/invisible, but that seems pretty silly. 我唯一想到的方法是捕获onContextMenuRequested,查看当前选择了哪个选项卡,并将各种MenuItems设置为可见/不可见,但这似乎很愚蠢。 Is there a better way of doing this? 有更好的方法吗?

Edit: Calrification - the tab contents are Panes (VBox, GridPane, etc.) so setting the ContextMenu directly on the content is sadly impossible. 编辑:Calrification-选项卡上的内容是窗格(VBox,GridPane等),因此直接在内容上设置ContextMenu是可惜的。

I can see two solutions to this. 我可以看到两种解决方案。 One is to set a single context menu on the tab pane. 一种是在选项卡窗格上设置单个上下文菜单。 Register a listener with the selected tab, and repopulate the context menu when the selection changes. 在选定的选项卡上注册一个侦听器,然后在选择更改时重新填充上下文菜单。

The other solution is just to set the context menu on the content of the tabs. 另一种解决方案是在选项卡的内容上设置上下文菜单。 Note that you can set a context menu on any node, by registering a handler for the contextMenuRequested event, and show the context menu. 请注意,可以通过注册contextMenuRequested事件的处理程序来在任何节点上设置上下文菜单,并显示上下文菜单。 You can set the same context menu on the tab. 您可以在选项卡上设置相同的上下文菜单。

This example demonstrates both techniques: 此示例演示了两种技术:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

public class TabPanesWithContextMenu extends Application {

    @Override
    public void start(Stage primaryStage) {
        TabPane tabPane1 = new TabPane();
        ContextMenu contextMenu = new ContextMenu();
        tabPane1.setContextMenu(contextMenu);

        List<MenuItem> tab1Items = new ArrayList<>();
        tab1Items.add(new MenuItem("Choice 1"));
        tab1Items.add(new MenuItem("Choice 2"));

        List<MenuItem> tab2Items = new ArrayList<>();
        tab2Items.add(new MenuItem("Choice 3"));
        tab2Items.add(new MenuItem("Choice 4"));

        Tab tab1 = new Tab("Tab 1");
        tab1.setContent(new Pane());
        Tab tab2 = new Tab("Tab 2");
        tab2.setContent(new Pane());
        tabPane1.getTabs().addAll(tab1, tab2);

        Map<Tab, List<MenuItem>> itemsByTab = new HashMap<>();
        itemsByTab.put(tab1, tab1Items);
        itemsByTab.put(tab2, tab2Items);

        tabPane1.getSelectionModel().selectedItemProperty().addListener((obs, oldTab, newTab) -> 
           contextMenu.getItems().setAll(itemsByTab.get(newTab)) );

        contextMenu.getItems().addAll(tab1Items);

        TabPane tabPane2 = new TabPane();

        Tab tab3 =  createTabWithContextMenu("Tab 3", new MenuItem("Choice 5"), new MenuItem("Choice 6"));
        Tab tab4 =  createTabWithContextMenu("Tab 4", new MenuItem("Choice 7"), new MenuItem("Choice 8"));

        tabPane2.getTabs().addAll(tab3, tab4);

        HBox root = new HBox(10, tabPane1, tabPane2);

        primaryStage.setScene(new Scene(root, 600, 600));
        primaryStage.show();
    }

    private Tab createTabWithContextMenu(String title, MenuItem... items) {
        Tab tab = new Tab(title);
        ContextMenu contextMenu = new ContextMenu(items);
        tab.setContextMenu(contextMenu);

        Pane content = new Pane();
        content.setOnContextMenuRequested(e -> 
            contextMenu.show(content, e.getScreenX(), e.getScreenY()));
        tab.setContent(content);

        return tab ;
    }

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM