Добавление JMenu в JPanel

Мне нужно иметь JMenu (со стрелкой справа, которая может отображать JMenuItem) в JPanel. Проблема в том, что когда я это делаю, JMenu не активируется при наведении курсора мыши... Я не знаю, как это сделать и возможно ли это.


person paranoia25    schedule 08.02.2013    source источник
comment
Вы добавляете JMenus к JMenuBar и вызываете метод setJMenuBar() JFrame - я не думаю, что вы можете добавить его к JPanel. И убедитесь, что ваш JMenu заполнен предметами!   -  person moonwave99    schedule 08.02.2013
comment
Привет, я знаю это решение, но это не то, что мне нужно. Я действительно хочу JMenu прямо в JPanel... Это проблема.   -  person paranoia25    schedule 08.02.2013
comment
Затем рассмотрите возможность использования JDesktopPane с JInternalFrames или определите свой собственный JComponent.   -  person moonwave99    schedule 08.02.2013
comment
Это старо, но я хотел указать, что этот ответ связан. stackoverflow.com/questions/4299846/add-jmenubar-to -a-jpanel   -  person ldmtwo    schedule 31.10.2016


Ответы (3)


Если вы завернете свой JMenu в JMenuBar, он будет работать как положено.

Вот демонстрационный пример:

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();
            }
        });
    }

}

Результат:

Результат добавления меню на панель содержимого JFrame

person Guillaume Polet    schedule 08.02.2013
comment
Привет! Это не тот внешний вид, который я хотел бы. Я хотел бы, чтобы JMenu появлялся прямо на панели (а не в JMenuBar). - person paranoia25; 08.02.2013
comment
@ paranoia25 ваш вопрос не совсем ясен. Если бы вы указали SSCCE, вы бы получили лучший ответ напрямую. Теперь, что касается вашей проблемы, я бы не добавлял JMenu непосредственно к JPanel, а скорее JButton с ActionListener, который открывает JPopupMenu. Чтобы JButton выглядело как JMenu, вам, вероятно, придется выполнить некоторые настройки и получить доступ к значениям по умолчанию L&F. - person Guillaume Polet; 08.02.2013
comment
+1 JToolBar может быть привлекательной альтернативой Container для JMenuBar, как показано здесь. - person trashgod; 08.02.2013

Вот еще один способ решить эту проблему, который, как мне кажется, ближе к тому, что вы хотите. Он включает в себя расширение JMenuBar, чтобы придать ему вид объекта JMenu.

Класс содержит JMenu объект, называемый меню. Методы добавления переопределены, поэтому вы добавляете в меню вместо JMenuBar (возможно, вам придется переопределить еще несколько методов добавления, чтобы сделать это идеальным).

Есть несколько вариантов с покраской. Я не был уверен, хотите ли вы, чтобы стиль кнопки выглядел как JMenuBar, поэтому я добавил несколько комментариев к некоторым параметрам, чтобы настроить его, а также внешний вид подчеркивания JMenuBar.

Вот результат просмотра кнопки без рамки: UnclickedНажато

Вот результат без кнопки и рамки: UnclickedНажато

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);
}
}
person Michael Peterson    schedule 27.03.2013
comment
Привет! Это более близкое решение! Но это все еще не совсем то, что я ищу. Я хотел бы JMenu непосредственно в JPanel. В вашем решении JMenu все еще находится в JMenuBar, и пользователь должен щелкнуть JMenuBar, чтобы увидеть и получить доступ к JMenu. - person paranoia25; 27.03.2013
comment
@ paranoia25, насколько я знаю, сделать это невозможно, потому что для работы вам нужен JMenuBar. В этом решении по-прежнему используется JMenuBar, но вы можете сделать так, чтобы он выглядел так, как будто его там нет, возясь с методами Paint. - person Michael Peterson; 07.04.2013

Вы должны передать BorderLayout в макете JPanel, а затем вы можете добавить строку меню в панель:

JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(menubar, BorderLayout.NORTH);
person Vuk Vasić    schedule 08.02.2013
comment
И что это изменит в JMenu? Замена FlowLayout на BorderLayout влияет на размер и расположение, но не на поведение. - person Guillaume Polet; 08.02.2013
comment
ЗДРАВСТВУЙ! Проблема в том, что мне нужен не JMenuBar в JPanel, а JMenu в JPanel. - person paranoia25; 08.02.2013