How to fix JPopupMenu get hidden inside the insets of the border?



I need to show a menu inside a dialog. However when the JPopupMenu gets hidden inside the border when the barder insets are large.

import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;

public class PopupMenuBorderInsetsBug {
    public static void main(String[] args) {
        JDialog popupDialog = new JDialog();
        popupDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        popupDialog.getRootPane().setBorder(new BorderWithInsets(Color.RED));

        JButton btnShowMenu = new JButton("Show Menu");

        JPopupMenu menu = new JPopupMenu();
        menu.add(new JMenuItem("Menu Item"));

        btnShowMenu.addActionListener(e -> menu.show(btnShowMenu, 0, btnShowMenu.getHeight()));
        popupDialog.add(btnShowMenu);

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

    private static class BorderWithInsets extends LineBorder {
        public BorderWithInsets(Color color) {
            super(color);
        }

        @Override
        public Insets getBorderInsets(Component c) {
            return new Insets(10, 10, 30, 10);
        }
    }
}

Above code creates a dialog box and when clicked on the button menu should appear but it get hidden inside the border inset. like this

If the insets of the border is changed as this return new Insets(10, 10, 10, 10);, menu shows without any problem. like this

Answer

The problem is due to the wrong use of root panes, you must put the components in the JDialog’s contentPane.

See the changes in main:

public static void main(String[] args) {
    JDialog popupDialog = new JDialog();
    popupDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

    //Use a JPanel as container and set insets and content on it
    JPanel content=new JPanel();
    content.setBorder(new BorderWithInsets(Color.RED));

    JButton btnShowMenu = new JButton("Show Menu");

    JPopupMenu menu = new JPopupMenu();
    menu.add(new JMenuItem("Menu Item"));

    btnShowMenu.addActionListener(e -> menu.show(btnShowMenu, 0, btnShowMenu.getHeight()));
    
    content.add(btnShowMenu);

    //Set the panel as contentPane for the dialog
    popupDialog.setContentPane(content);
    popupDialog.pack();
    popupDialog.setVisible(true);
}


Source: stackoverflow