2

I am trying to create a equally spaced menu inside a JFrame. By unequally spaced menu, I mean that the width of the menu item varies with the text that we put into that menu.Right now, my menu looks like this :



I would like my menu to look something like this


enter image description here


Can I do that ? Do I need to use layout managers to do that ?

OneMoreError
  • 7,518
  • 20
  • 73
  • 112

3 Answers3

2

You could also use a JToolBar with a GridLayout(1, 0) to get even spacing.

Catalina Island
  • 7,027
  • 2
  • 23
  • 42
  • +1 for JToolBar (even though the requirement seems to be a menuBar, this might be a viable alternative) – kleopatra Sep 19 '12 at 12:57
2

Do I need to use layout managers to do that ?

short answer: yes :-)

Longer answer: the menu/-bar is a bit special in that some layoutManagers don't do as one (read: me) would expect. Simplest that comes to mind is a one-row GridLayout:

// sanity check: does grid respect component alignment?
// manager does, but menu internal layout doesn't
JComponent content = new JPanel(new GridLayout(3, 3));
for (int i = 0; i < 9; i++) {
    if (i % 2 == 0) {
        JMenu menu = new JMenu("menu: " + i);
        menu.setBorderPainted(true);
        menu.setBorder(BorderFactory.createLineBorder(Color.GREEN));
        menu.setHorizontalAlignment(JMenu.CENTER);
        content.add(menu);
    } else {
        JLabel menu = new JLabel("label: " + i);
        menu.setBorder(BorderFactory.createLineBorder(Color.GREEN));
        menu.setHorizontalAlignment(JMenu.CENTER);
        content.add(menu);
    }
}
JXFrame frame = wrapInFrame(content, "menuBar with GridLayout");
JMenuBar bar = getMenuBar(frame);
// not surprisingly (after sanity check), 
// horizontal align isn't respected in the menubar as well
bar.setLayout(new GridLayout(1, 0));
JMenu menu = new JMenu("some dummy");
menu.setBorderPainted(true);
menu.setBorder(BorderFactory.createLineBorder(Color.GREEN));
menu.setHorizontalAlignment(JMenu.CENTER);
bar.add(menu);
bar.add(new JMenu("other"));
show(frame, 500, 500);

The sanity check demonstrates that the JMenu has its own ideas about how they are layout out: the content is always leading-aligned (the exact distance is LAF and is- or not-topLevelMenu). That's hard-coded in BasicMenuItem.paintMenuItem, internally using the MenuItemLayoutHelper.

So the simplest manager does size and locate them as expected, but can't do anything in centering the individual items.

If centering is needed, you can use a trick (not recommended, though [1]): based on the implementation details that

  • the default layoutManger is-a BoxLayout and
  • a topLevelMenu has a maxSize == prefSize

you can add glues before/after each item:

JMenu menu = new JMenu("some dummy");
menu.setBorderPainted(true);
menu.setBorder(BorderFactory.createLineBorder(Color.GREEN));
menu.setHorizontalAlignment(JMenu.CENTER);
bar.add(Box.createHorizontalGlue());
bar.add(menu);
bar.add(Box.createHorizontalGlue());
bar.add(new JMenu("other"));
bar.add(Box.createHorizontalGlue());

With that, they appear centered and evenly distributed across the menubar width: the (could-be, depends on requirement) drawback is that the menus are sized at their pref, that is don't fill the entire bar.

[1] same effect is doable cleanly, without relying on implemetation details, with a powerful-enough manger, like f.i. MigLayout

bar.setLayout(new MigLayout("fill, insets 0", "[center]"));
kleopatra
  • 51,061
  • 28
  • 99
  • 211
-1

Set the preferred size on each menu item to be the same.

jMenu1.setPreferredSize(new java.awt.Dimension(80, 21));
jMenu2.setPreferredSize(new java.awt.Dimension(80, 21));
jMenu3.setPreferredSize(new java.awt.Dimension(80, 21));
BillRobertson42
  • 12,602
  • 4
  • 40
  • 57
  • 6
    What if the menu font size changes?? What if the text is large then 80px?? – MadProgrammer Sep 19 '12 at 05:18
  • Ok.. It worked. Can I also set the text alignment within that space, like place it at the center of the space or to the right ?? – OneMoreError Sep 19 '12 at 05:19
  • 2
    no, whatever the problem, setXXSize is *not* the answer .. [some reasons](http://stackoverflow.com/questions/7229226/should-i-avoid-the-use-of-setpreferredmaximumminimumsize-methods-in-java-swi/7229519#7229519) – kleopatra Sep 19 '12 at 08:51