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.
Another example:
MenuSelectionManager.defaultManager().setSelectedPath(
new MenuElement[] {popup, menuB, menuB.getPopupMenu()});
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AutoExpandSubMenusDemo2 extends JFrame {
private final JPopupMenu popup = new JPopupMenu("Popup");
public AutoExpandSubMenusDemo2() {
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"));
JPanel buttonPanel = new JPanel();
buttonPanel.add(new JButton(new AbstractAction("Show menuB Popup") {
@Override public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
popup.show(button, 0, button.getHeight());
//[Bug ID: JDK-6949414 JMenu.buildMenuElementArray() endless loop]
//( http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6949414 )
//menuB.doClick();
MenuSelectionManager.defaultManager().setSelectedPath(
new MenuElement[] {popup, menuB, menuB.getPopupMenu()});
}
}));
buttonPanel.add(new JButton(new AbstractAction("Select menuY") {
@Override public void actionPerformed(ActionEvent e) {
JButton button = (JButton) e.getSource();
popup.show(button, 0, button.getHeight());
MenuSelectionManager.defaultManager().setSelectedPath(
new MenuElement[] {popup, menuB, menuB.getPopupMenu(), menuY});
}
}));
getContentPane().add(buttonPanel);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new AutoExpandSubMenusDemo2();
f.setSize(500, 300);
f.setVisible(true);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With