Search code examples
javaswingjmenuitemjmenubar

Swing - last JMenuItem occupy the rest of space on JMenuBar


I find that if I have a JMenuBar, and the last element of it (the rightmost one) is a JMenuItem, it will occupy all the rest blank space on the JMenuBar, which is definitely not what we want.

Imagine an "About" JMenuItem as the rightmost item on a JMenuBar. It should only occupy the same space as the other menus.

See my SSCCE: (click the menu and hover over the menuitem on the right to see the effect)

import java.awt.Dimension;

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

public class JMenuItemLastOnMenuBar {

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

            @Override
            public void run() {
                createGUI();
            }
        });
    }

    private static void createGUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setBounds(0, 0, 300, 300);

        JMenuBar bar = new JMenuBar();
        JMenu menu = new JMenu("Menu 1");
        JMenuItem item1 = new JMenuItem("Item 1");
        menu.add(item1);
        bar.add(menu);

        JMenuItem item2 = new JMenuItem("Item 2") {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(120, 25);
            }
        };
        bar.add(item2);

        frame.setJMenuBar(bar);

        frame.pack();
        frame.setVisible(true);
    }

}

Solution

  • You should override the method getMaximumSize

    import java.awt.Dimension;
    
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.SwingUtilities;
    
    public class JMenuItemLastOnMenuBar {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    createGUI();
                }
            });
        }
    
        private static void createGUI() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.setBounds(0, 0, 300, 300);
    
            JMenuBar bar = new JMenuBar();
            JMenu menu = new JMenu("Menu 1");
            JMenuItem item1 = new JMenuItem("Item 1");
            menu.add(item1);
            bar.add(menu);
    
            JMenuItem item2 = new JMenuItem("Item 2") {
                @Override
                public Dimension getMaximumSize() {
                    Dimension d1 = super.getPreferredSize();
                    Dimension d2 = super.getMaximumSize();
                    d2.width = d1.width;
                    return d2;
                }
            };
            bar.add(item2);
    
            frame.setJMenuBar(bar);
    
            frame.pack();
            frame.setVisible(true);
        }
    
    }