stefita
stefita

Reputation: 1793

JMenuItem setMinimumSize doesn't work

I try to set a minimum width for my menu items, but it doesn't seem to work. Here is my function, which creates the items:

 private JMenuItem newItem(String text, String iconPath) {
     JMenuItem myMenuItem;
     if (iconPath == null || iconPath.isEmpty()) {
         myMenuItem = new JMenuItem(text);
     }
     else {
         ImageIcon icon = new ImageIcon(iconPath);
         myMenuItem = new JMenuItem(text, icon);
     }
     // this would work, but then setMaximumSize doesn't have any effect
     // myMenuItem.setPreferredSize(new Dimension(250,20)); 
     myMenuItem.setMinimumSize(new Dimension(250,20)); 
     myMenuItem.setMaximumSize(new Dimension(350,20));

     return myMenuItem;
 }

What am I doing wrong?

PS. I'm using jdk1.6 on Windows XP, Servicepack 3 with the System Look&Feel

Upvotes: 2

Views: 5359

Answers (4)

Nico
Nico

Reputation: 1956

i replaced your

myMenuItem.setMinimumSize(new Dimension(250, 20));
myMenuItem.setMaximumSize(new Dimension(350, 20));

with

myMenuItem.setPreferredSize(new Dimension(250, 20));

and it makes it the width you were looking for. In my experience swing components respond better to preferred size than min and max size.

EDIT:

after taking another stab i think this works pretty well.. it boils down to much the same as you have and i think it'll work no matter what the font (where as you've hardcoded the font).

it does however not take into account the leading gutter of a menu item, but unless you're text is really significantly long it shouldn't make a difference..

 private JMenuItem newItem(String text, String iconPath) {
    JMenuItem myMenuItem;
    if (iconPath == null || iconPath.isEmpty()) {
        myMenuItem = new JMenuItem(text);
        myMenuItem.setPreferredSize(new Dimension(myMenuItem.getFontMetrics(myMenuItem.getFont()).stringWidth(text), 20));
    } else {
        ImageIcon icon = new ImageIcon(iconPath);
        myMenuItem = new JMenuItem(text, icon);
        myMenuItem.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
    }
    return myMenuItem;
}

Upvotes: 1

Russ Hayward
Russ Hayward

Reputation: 5667

Minimum and maximum sizes are ignored by most layout managers. Here is a useful little trick that forces those sizes to be respected in any layout manager:

private class MyMenuItem extends JMenuItem {
    @Override
    public Dimension getPreferredSize() {
        Dimension preferred = super.getPreferredSize();
        Dimension minimum = getMinimumSize();
        Dimension maximum = getMaximumSize();
        preferred.width = Math.min(Math.max(preferred.width, minimum.width), 
            maximum.width);
        preferred.height = Math.min(Math.max(preferred.height, minimum.height), 
            maximum.height);
        return preferred;
    }
}

This has the advantage of working even if the contents of the menu item changes. You will need to add constructors to suit your purposes.

Upvotes: 4

camickr
camickr

Reputation: 324137

If I understand the question I'm not sure why you need to use the FontMetrics. Just invoke getPreferredSize() on the menu item. If the preferred size is less than your minimum then reset the preferred size to your minimum.

Upvotes: 0

stefita
stefita

Reputation: 1793

Ok, so I found A solution, perhaps not the best one but it seems to work. I'm still a bit worried about the FontMetrics statement, though. So if anyone has a better solution, I would be glad to see it. Here is my code (Menu.MINWIDTH is set to 200 and Menu.MAXWIDTH to 300):

 private JMenuItem newItem(String text, String iconPath) {
     JMenuItem myMenuItem;
     ImageIcon icon= null;
     int iconPixels = 0;
     if (iconPath == null || iconPath.isEmpty()) {
         myMenuItem = new JMenuItem(text);
     }
     else {
         icon = new ImageIcon(iconPath);
         myMenuItem = new JMenuItem(text, icon);
         iconPixels = icon.getIconWidth();
     }

     FontMetrics fontM = myMenuItem.getFontMetrics(new Font("Default", Font.PLAIN, 12));
     int stringPixels = fontM.stringWidth(text);

     int newWidth = stringPixels + iconPixels;

     newWidth = newWidth < Menu.MINWIDTH ? Menu.MINWIDTH : newWidth;
     newWidth = newWidth > Menu.MAXWIDTH ? Menu.MAXWIDTH : newWidth;

     myMenuItem.setPreferredSize(new Dimension(newWidth, 20)); 
     System.out.println(text + " - " + newWidth);
     return myMenuItem;
 }

Upvotes: 0

Related Questions