Adding a clickable, action-firing JMenuItem directly to a JMenuBar?

thedude19 picture thedude19 · Dec 7, 2009 · Viewed 9k times · Source

Is there a way to add a JMenuItem (or similar button-type object) to a JMenuBar?

Adding a JMenuItem doesn't play well with the layout of a JMenuBar, and buttons look too button-like.

Should we be tweaking the button to look like a JMenuItem or tweaking the JMenuBar to display the JMenuItem correctly? Or something else altogether?

Answer

Carl Smotricz picture Carl Smotricz · Dec 7, 2009

The following code implements camickr's solution, although I would have come up with the same thing after seeing the default way JMenuItems are rendered in a JMenuBar. It looks reasonably authentic and responds to clicks, but not to the mnemonic.

I tried giving the JMenuItems accelerators (see code) and that works but that looks really weird.

public class TheDude19 extends JFrame {

   private class Action1 extends AbstractAction {
      private Action1() {
         super("Action1");
         putValue(MNEMONIC_KEY, (int) '1');
         // putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_A, KeyEvent.CTRL_MASK));
      }
      public void actionPerformed(ActionEvent arg0) {
         System.out.println("Action 1!");
      }
   }
   private class Action2 extends AbstractAction {
      private Action2() {
         super("Action2");
         putValue(MNEMONIC_KEY, (int) '2');
      }
      public void actionPerformed(ActionEvent arg0) {
         System.out.println("Action 2!");
      }
   }
   private class NarrowMenuItem extends JMenuItem {

      public NarrowMenuItem(Action a) {
         super(a);
      }
      public Dimension getMaximumSize() {
         return new Dimension(super.getPreferredSize().width, super.getMaximumSize().height);
      }
   }
   public TheDude19() {
      JMenuItem menu1 = new NarrowMenuItem(new Action1());
      JMenuItem menu2 = new NarrowMenuItem(new Action2());
      JMenuBar mb = new JMenuBar();
      mb.add(menu1);
      mb.add(menu2);
      add(mb, BorderLayout.NORTH);
      setSize(400, 300);
   }

   public static void main(String[] args) {
      (new TheDude19()).setVisible(true);
   }

}