Question

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);
            }
        });
    }
}
Était-ce utile?

La solution 2

What's preferred size of the JPopupMenu before showing?

Autres conseils

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);

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

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);
   }
});
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top