SeniorJD
SeniorJD

Reputation: 7212

Get JPopupMenu size before it is shown

I have the JPopupMenu shown on right mouse click. I want JPopupMenu' top right corner to be at the click location (not top left one, as default). To perform this, I need to set the X coordinate as mouseEvent.getX() - popupMenu.getWidth(). The problem is, before popup is shown first time, its width equals 0.

SSCCE:

public class PopupTest2 {
    public static void main(String[] a) {
        final JFrame frame = new JFrame();
        frame.setSize(500, 500);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createLineBorder(Color.RED));

        final JPopupMenu menu = new JPopupMenu();

        for (int i = 0; i < 10; i++) {
            JMenuItem item = new JMenuItem("Item #"+String.valueOf(i));
            menu.add(item);
        }

        panel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON3) {
                    // first time works wrong
                    menu.show(panel, e.getX() - menu.getWidth(), e.getY());
                }
            }
        });
        frame.setContentPane(panel);
        frame.setUndecorated(true);
        frame.setBackground(new Color(50, 50, 50, 200));

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                frame.setVisible(true);
            }
        });
    }
}

Upvotes: 4

Views: 2051

Answers (4)

pedromateo
pedromateo

Reputation: 3125

Using popup.getPreferredSize().width and popup.getPreferredSize().height you can get popup size before it is shown.

This is an example locating the popup menu at the top of a button:

but_menu = new JButton("");
but_menu.addMouseListener(new MouseAdapter() {
   public void mousePressed(MouseEvent e) {
      Point p = but_menu.getLocation();
      Point dest = new Point();
      dest.x = 0 - popup.getPreferredSize().width + but_menu.getWidth();
      dest.y = 0 - popup.getPreferredSize().height;
      popup.show(but_menu,dest.x,dest.y);
   }
});

Upvotes: 1

StanislavL
StanislavL

Reputation: 57421

What's preferred size of the JPopupMenu before showing?

Upvotes: 2

kleopatra
kleopatra

Reputation: 51535

Using the preferredSize (as already mentioned) is the way to go for getting the location.

But (being on a quest here :-): manually showing the popup is not the recommended approach. A really clean implementation will use the componentPopupMenu property and implement getPopupLocation as needed, something like

JPanel panel = new JPanel(new BorderLayout()) {

    @Override
    public Point getPopupLocation(MouseEvent event) {
        JPopupMenu menu = getComponentPopupMenu();
        if (menu == null || event == null) return null;
        return new Point(event.getX() - menu.getPreferredSize().width, event.getY());
    }

};
JPopupMenu menu = new JPopupMenu();
panel.setComponentPopupMenu(menu);

Upvotes: 5

Sergiy Medvynskyy
Sergiy Medvynskyy

Reputation: 11327

Probably you can determine the width of context menu as the highest preferred width of ist elements?

Upvotes: 1

Related Questions