javaswingparentjmenuitem

Get the Window for a JMenuItem?


Is there a way to get the Window which a JMenuItem belongs to? I tried this proof of-concept:

JFrame testFrame = new JFrame();
testFrame.setSize(300, 100);
testFrame.setLocationRelativeTo(null);

JMenuBar testBar = new JMenuBar();
JMenu testMenu = new JMenu("Test");
JMenuItem testItem = new JMenuItem("Parent Test");

testItem.addActionListener(e -> {
    System.out.println("Has Top Level Ancestor: " + (testItem.getTopLevelAncestor() != null));
    System.out.println("Has Window Ancestor: " + (SwingUtilities.getWindowAncestor(testItem) != null));
});

testBar.add(testMenu);
testMenu.add(testItem);

testFrame.setJMenuBar(testBar);
testFrame.setVisible(true);

The output was:

Has Top Level Ancestor: false
Has Window Ancestor: false

Solution

  • I changed it to print the parent of the menu item:

    testItem.addActionListener(e -> System.out.println(testItem.getParent().getClass().getSimpleName()));
    

    It prints "JPopupMenu" rather than "JMenu", which means that testMenu is not the parent of testMenuItem. However, if you cast the parent class and call JPopupMenu#getInvoker, it will return the JMenu.

    With this in mind, I created the following method:

    private static Window getWindowAncestor(JMenuItem item) {
        Container parent = item.getParent();
        if (parent instanceof JPopupMenu)
            return SwingUtilities.getWindowAncestor(((JPopupMenu) parent).getInvoker());
        else if (parent instanceof Window)
            return (Window) parent;
        else
            return SwingUtilities.getWindowAncestor(parent);
    }
    

    It works :)