2

I need to have a JMenu (the one with the arrow on right which can display JMenuItem) in a JPanel. The problem is that when I do that the JMenu is not activate on mouse rollover... I don't know how to do that and if it's possible.

paranoia25
  • 626
  • 1
  • 5
  • 23
  • 2
    You add `JMenu`s to a `JMenuBar`, and you call `setJMenuBar()` method of a `JFrame` - I don't think you can add it to a `JPanel`. And be sure that your `JMenu` is filled with items! – moonwave99 Feb 08 '13 at 11:25
  • Hi, I know this solution but it is not the one I want. I really want a JMenu directly into a JPanel... This is the problem. – paranoia25 Feb 08 '13 at 12:46
  • Then consider using a `JDesktopPane` with `JInternalFrames`, or define your own `JComponent`. – moonwave99 Feb 08 '13 at 13:08
  • This is old, but I wanted to point out this answer is related. http://stackoverflow.com/questions/4299846/add-jmenubar-to-a-jpanel – ldmtwo Oct 30 '16 at 23:06

3 Answers3

3

If you wrap your JMenu in a JMenuBar, it works as expected.

Here is a demo example:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class TestMenus {

    private JMenuBar createMenuBar(String name, int depth) {
        JMenuBar bar = new JMenuBar();
        bar.add(createMenu(name, depth));
        return bar;
    }

    private JMenu createMenu(String name, int depth) {
        JMenu menu = new JMenu(name);
        for (int i = 0; i < 5; i++) {
            if (depth > 0) {
                menu.add(createMenu("sub-" + name, depth - 1));
            }
        }
        for (int i = 0; i < 5; i++) {
            menu.add(createMenuItem("Menu item " + (i + 1)));
        }
        return menu;
    }

    private JMenuItem createMenuItem(String name) {
        final JMenuItem jMenuItem = new JMenuItem(name);
        jMenuItem.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showMessageDialog(jMenuItem, "Successfully pressed a menu item");
            }
        });
        return jMenuItem;
    }

    protected void initUI() {
        JFrame frame = new JFrame(TestMenus.class.getSimpleName());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(createMenuBar("Root menu", 3));
        frame.pack();
        frame.setVisible(true);
    }

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

            @Override
            public void run() {
                new TestMenus().initUI();
            }
        });
    }

}

An the result:

Result of menus added to a JFrame content pane

Guillaume Polet
  • 47,259
  • 4
  • 83
  • 117
  • Hi! This is not the look I would like. I would like that the JMenu appear directly in the panel (not the the JMenuBar). – paranoia25 Feb 08 '13 at 12:44
  • 2
    @paranoia25 your question is not clear about that. If you had put an [SSCCE](http://sscce.org) you would have got a better answer directly. Now regarding your problem, I would not add a `JMenu` directly to the `JPanel` but rather a `JButton` with an `ActionListener` that opens a `JPopupMenu`. To make the `JButton` look like a `JMenu`, you will probably have to make some customisation and access L&F defaults. – Guillaume Polet Feb 08 '13 at 12:55
  • 3
    +1 A `JToolBar` may be an appealing alternative `Container` for the `JMenuBar`, as shown [here](http://stackoverflow.com/a/14630345/230513). – trashgod Feb 08 '13 at 15:15
2

Here is another way to solve this which I think is closer to what you want. It involves extending JMenuBar to give it the look of a JMenu Object.

The class contains a JMenu Object called menu. The add methods are overridden so you are adding to menu instead of the JMenuBar (You may have to override a few more add methods to make this perfect).

There are a few options with painting. I wasn't sure if you wanted the button style look of the JMenuBar, so I included a few comments on some options to customize that, as well as the underline look of the JMenuBar.

Here is the result of the button look with no border: Unclicked Clicked

Here is the result with no button look and no border: Unclicked Clicked

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

public class JPanelMenu extends JMenuBar{

public static void main(String[] args) {
    JFrame f = new JFrame("Menu Test");
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JMenu jmenu = new JMenu("J Menu");
    jmenu.add(new JMenuItem("Menu Item"));

    JPanelMenu m = new JPanelMenu("Menu");
    m.add(jmenu);
    m.add(new JMenuItem("Menu Item 1"));
    m.add(new JMenuItem("Menu Item 2"));

    JPanel background = new JPanel();
    background.add(m);      
    f.setContentPane(background);
    f.pack();
    f.setVisible(true);
}

//This is the JMenu that is shown
private JMenu menu;

public JPanelMenu(String title) {
    super();
    menu = new JMenu(title);
    super.add(menu);
}

@Override
public Component add(Component comp) {
    //You add the the JMenu instead of the JMenuBar
    return menu.add(comp);
}

@Override
public JMenu add(JMenu c) {
    //You add the the JMenu instead of the JMenuBar
    return (JMenu) menu.add(c);
}

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    //Include these two lines to remove the button look
    //Or remove this method to keep the button look
    //g.setColor(getBackground());
    //g.fillRect(0, 0, getWidth(), getHeight());
}

@Override
protected void paintBorder(Graphics g) {
    //Remove this line to remove the underline look
    //when you remove the button look
    //An alternative is to you setBorderPainted(false);
    //when you create the object or in the constructor
    //Or remove this method to keep the border
    //super.paintBorder(g);
}
}
Michael Peterson
  • 348
  • 6
  • 22
  • Hi! This is the closer solution! But this is still not exactly what I'm looking for. I would like a JMenu directly in a JPanel.In your solution the JMenu is still in a JMenuBar and the user has to clik on the JMenuBar to see and access to the JMenu. – paranoia25 Mar 27 '13 at 07:08
  • @paranoia25 as far as I know, there is no way to do that because you need a JMenuBar for it to work. This solution still uses a JMenuBar, but you can make it look as through there is not one there by messing with the Paint methods. – Michael Peterson Apr 07 '13 at 02:08
0

You must pass a BorderLayout in JPanel layout then you can add menu bar in panel:

JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(menubar, BorderLayout.NORTH);
Vuk Vasić
  • 1,398
  • 10
  • 27