Rich Hoffman
Rich Hoffman

Reputation: 762

Can't Add JMenuItem to JMenu in JPopupMenu

I've got a new UI I'm working on implementing in Java and I'm having trouble implementing a JPopupMenu containing a JMenu (as well as several JMenuItems), which itself contains several JMenuItems. The JPopupMenu appears where I click the RMB, and it looks good, but the "Connect" JMenu doesn't seem to have any children when I mouse-over, despite my best efforts to .add() them.
enter image description here

Having looked at several examples online, I haven't seen any that specifically implement a listener for mouseEntered() to roll out the sub-items. I'm of a mind that I'm messing something up in my menu initialization method.

I've attached the pertinent code for your perusal.

//Elsewhere...
private JPopupMenu _clickMenu;
//End Elsehwere...

private void initializeMenu()
{
    _clickMenu = new JPopupMenu();
    _clickMenu.setVisible(false);

    _clickMenu.add(generateConnectionMenu());

    JMenuItem menuItem;
    menuItem = new JMenuItem("Configure");
    addMenuItemListeners(menuItem);
    _clickMenu.add(menuItem);

    menuItem = new JMenuItem("Status");
    addMenuItemListeners(menuItem);
    _clickMenu.add(menuItem);
}

private JMenu generateConnectionMenu()
{
    JMenu menu = new JMenu("Connect");

    List<Port> portList = _database.getAllPortsInCard(_cardId);

    for(int i = 0; i < portList.size(); i++)
    {
        menu.add(new JMenuItem(portList.get(i).getName()));
    }

    return menu;
}

The code is certainly not the prettiest, but go easy on me as it's been altered too many times today as time permitted while I tried to figure out why this wasn't working. I'm thinking it may be a question of scope, but I've tried a few different code configurations to no avail. Feel free to ask any followup questions or smack me for an obvious oversight (it's happened before...). Thanks all!

Edit: Chalk this one up to a lack of experience with Java and Swing... I was manually positioning and making the JPopupMenu visible instead of using the JComponent.setComponentPopupMenu(menu) method. After doing this for the card module in the above image (itself a JButton), the submenu displays correctly. A different, functional version of the initialization code is included below.

    private void initializeMenu()
{
    _cardMenu = new JPopupMenu();

    JMenu menu = new JMenu("Connect");

    JMenuItem menuItem;
    menuItem = new JMenuItem("1");
    menu.add(menuItem);

    menuItem = new JMenuItem("2");
    menu.add(menuItem);

    _cardMenu.add(menu);
    _cardMenu.add(new JMenuItem("Configure"));
    _cardMenu.add(new JMenuItem("Status"));

    _mainButton.setComponentPopupMenu(_cardMenu); //Important, apparently!
}

So, lesson learned. Thanks for the help guys!

Upvotes: 2

Views: 2542

Answers (2)

mKorbel
mKorbel

Reputation: 109823

This is common Bug or Swing property that in one moment can be visible only one Lightweight popup window, same issue is e.g. with popup from JComboBox added into JPopupMenu,

  • change Lightweight property to the Heavyweight

better would be

  • use un_decorated JDialog or JOptionPane with JComponents

EDIT @trashgod

  • everything works as I excepted, all JMenus, JMenuItems are visible and repeatly fired correct evets

code

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class ContextMenu implements ActionListener, MenuListener, MenuKeyListener {

    private JTextArea textArea = new JTextArea();

    public ContextMenu() {
        final JPopupMenu contextMenu = new JPopupMenu("Edit");
        JMenu menu = new JMenu("Sub Menu");
        menu.add(makeMenuItem("Sub Menu Save"));
        menu.add(makeMenuItem("Sub Menu Save As"));
        menu.add(makeMenuItem("Sub Menu Close"));
        menu.addMenuListener(this);
        JMenu menu1 = new JMenu("Sub Menu");
        menu1.add(makeMenuItem("Deepest Sub Menu Save"));
        menu1.add(makeMenuItem("Deepest Sub Menu Save As"));
        menu1.add(makeMenuItem("Deepest Sub Menu Close"));
        menu.add(menu1);
        menu1.addMenuListener(this);
        contextMenu.add(menu);
        contextMenu.add(makeMenuItem("Plain Save"));
        contextMenu.add(makeMenuItem("Plain Save As"));
        contextMenu.add(makeMenuItem("Plain Close"));
        contextMenu.addMenuKeyListener(this);
        JFrame frame = new JFrame();
        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        frame.add(panel);
        panel.setComponentPopupMenu(contextMenu);
        textArea.setInheritsPopupMenu(true);
        panel.add(BorderLayout.CENTER, textArea);
        JTextField textField = new JTextField();
        textField.setInheritsPopupMenu(true);
        panel.add(BorderLayout.SOUTH, textField);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 200);
        frame.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        textArea.append(e.getActionCommand() + "\n");
    }

    private JMenuItem makeMenuItem(String label) {
        JMenuItem item = new JMenuItem(label);
        item.addActionListener(this);
        return item;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ContextMenu contextMenu = new ContextMenu();
            }
        });
    }

    public void menuSelected(MenuEvent e) {
        textArea.append("menuSelected" + "\n");
    }

    public void menuDeselected(MenuEvent e) {
        textArea.append("menuDeselected" + "\n");
    }

    public void menuCanceled(MenuEvent e) {
        textArea.append("menuCanceled" + "\n");
    }

    public void menuKeyTyped(MenuKeyEvent e) {
        textArea.append("menuKeyTyped" + "\n");
    }

    public void menuKeyPressed(MenuKeyEvent e) {
        textArea.append("menuKeyPressed" + "\n");
    }

    public void menuKeyReleased(MenuKeyEvent e) {
        textArea.append("menuKeyReleased" + "\n");
    }
}

Upvotes: 2

trashgod
trashgod

Reputation: 205875

I don't see an obvious problem in the code shown, although @mKorbel's point may apply. For reference, this ControlPanel adds a subMenu with several items.

Upvotes: 2

Related Questions