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

时间:2015-11-30 21:58:58

标签: java user-interface javafx tabs

我想要一个带有多个标签的TabPane,每个标签的上下文菜单都不同。

在TabPane上设置ContextMenu显然会导致使用相同的ContextMenu,无论选择的选项卡如何。我尝试在不同的Tabs上设置不同的ContextMenus,但这有两个不需要的效果:

  1. 仅在右键单击选项卡标题时打开上下文菜单(而在TabPane上设置它允许右键单击选项卡内的任何位置)。我希望用户能够从选项卡内的任何位置访问上下文菜单,而不仅仅是标题。

  2. 右键单击一个标题页而选择另一个标题页仍然会打开单击选项卡的上下文菜单 - 我希望上下文菜单取决于当前所选的选项卡。

  3. 我能想到如何做的唯一方法是捕获onContextMenuRequested,查看当前选中的哪个选项卡,并设置各种MenuItem可见/不可见,但这看起来很傻。有没有更好的方法呢?

    编辑:校正 - 选项卡内容是Panes(VBox,GridPane等),因此很难直接在内容上设置ContextMenu。

1 个答案:

答案 0 :(得分:1)

我可以看到两个解决方案。一种是在选项卡窗格上设置单个上下文菜单。使用所选选项卡注册侦听器,并在选择更改时重新填充上下文菜单。

另一种解决方案是在选项卡的内容上设置上下文菜单。请注意,您可以通过注册contextMenuRequested事件的处理程序在任何节点上设置上下文菜单,并显示上下文菜单。您可以在选项卡上设置相同的上下文菜单。

此示例演示了两种技术:

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);
    }
}