Get the Window for a JMenuItem?

45 Views Asked by At

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
1

There are 1 best solutions below

2
Cardinal System On BEST ANSWER

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 :)