I would like to programmatically expand a particular JMenuItem in a JPopup. For example in the code below
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
public class AutoExpandSubMenusDemo extends JFrame {
private final JPopupMenu popup = new JPopupMenu("Popup");
public AutoExpandSubMenusDemo() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
JMenu menuB = new JMenu("B");
menuB.add(new JMenuItem("X"));
JMenuItem menuY = menuB.add(new JMenuItem("Y"));
menuB.add(new JMenuItem("Z"));
popup.add(new JMenuItem("A"));
popup.add(menuB);
popup.add(new JMenuItem("C"));
final JButton button = new JButton("Show Popup Menu");
button.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
popup.show(button, 0, button.getHeight());
// Show menuY
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
getContentPane().add(buttonPanel);
}
public static void main(String[] args) {
AutoExpandSubMenusDemo f = new AutoExpandSubMenusDemo();
f.setSize(500, 300);
f.setVisible(true);
}
}
I would like to expand the popup menu so that the items B(menuB)/Y(menuY) are expanded and selected when the button is pressed.
Sorry if this is something that's easy to do but I've searched around and can't figure it out.
I did find the
MenuSelectionManager.defaultManager().setSelectedPath(...)
however this didn't work when I tried it and the javadoc specifies that it is called from the LaF and should not be called by clients.
Any help is much appreciated.
While I don't recommend doing this, since the documentation itself advises against it, here's how you could do it:
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;
public class AutoExpandSubMenusDemo extends JFrame {
private final JPopupMenu popup = new JPopupMenu("Popup");
public AutoExpandSubMenusDemo() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
final JMenu menuB = new JMenu("B");
menuB.add(new JMenuItem("X"));
final JMenuItem menuY = menuB.add(new JMenuItem("Y"));
menuB.add(new JMenuItem("Z"));
popup.add(new JMenuItem("A"));
popup.add(menuB);
popup.add(new JMenuItem("C"));
final JButton button = new JButton("Show Popup Menu");
button.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
popup.show(button, 0, button.getHeight());
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuB.setPopupMenuVisible(true);
MenuSelectionManager.defaultManager().setSelectedPath(new MenuElement[]{popup, menuB, menuY});
}
});
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(button);
getContentPane().add(buttonPanel);
}
public static void main(String[] args) {
AutoExpandSubMenusDemo f = new AutoExpandSubMenusDemo();
f.setSize(500, 300);
f.setVisible(true);
}
}
Most of this code is yours. I only added:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuB.setPopupMenuVisible(true);
MenuSelectionManager.defaultManager().setSelectedPath(new MenuElement[]{popup, menuB, menuY});
}
});
which seems to work.
You could avoid abusing MenuSelectionManager
via 'MenuItem.setArmed(boolean)'.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
menuB.setPopupMenuVisible(true);
menuB.setArmed(true);
menuY.setArmed(true);
}
});
The popup staying visible after selecting another menu item or dismissing the JPopupMenu
still needs to be addressed though.
Another way is to fake a mouse event... :D
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MouseEvent event = new MouseEvent(
menuB, MouseEvent.MOUSE_ENTERED, 0, 0, 0, 0, 0, false);
menuB.dispatchEvent(event);
menuY.setArmed(true);
}
});
This way it is as if the user actually used the mouse.