0

I have a JContextMenu that I open in a JDialog by calling (the MouseListener is registered to the JDialog):

menu.show(e.getComponent(), e.getX(), e.getY());

The menu itself has an ActionListener registered on the menuitems. It opens fine and the actions are performed as expected, until I open another menu (for example the application's main menu or a context menu on another component) that overlaps something else. For example if a menu in the main menu bar overlaps a dialog or if a context menu is opened that reaches outside the window. Then the clicks on the context menu of the JDialog just close the context menu, as if you had clicked beside the menu to close it (the other menus in the application are still fine though).

It's as if the click goes through the menu. If I select a menu item with the arrow keys and press enter, it does the action just fine.

If I specify e.g. the main window of the application as invoker in the menu.show(), then it seems to always work (but of course it opens on the wrong location). What seems to work is registering the mouse listener on the content pane of the JDialog instead.

Can anyone explain what can cause this behaviour? Should a JDialog not be used as invoker of a context menu for some reason?

I also tried using setComponentPopupMenu(), but that only seems to exist for JComponent and not JDialog or it's content pane. Using it on a component inside the JDialog works, but so does the other method of using a mouse listener and menu.show().

user2375667
  • 463
  • 3
  • 10

1 Answers1

3

Absent a complete example, I'm not sure I can explain your result, but setComponentPopupMenu() works on a JPanel added to a dialog's content pane. The code below is based on this example.

image

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;

/**
 * @see https://stackoverflow.com/a/22100940/230513
 * @see https://stackoverflow.com/questions/5129294
 */
public class Test {

    private void display() {
        JDialog d = new JDialog();
        d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        final ImagePanel imagePanel = new ImagePanel();
        d.add(new JScrollPane(imagePanel));
        d.setJMenuBar(imagePanel.menuBar);
        d.pack();
        d.setLocationRelativeTo(null);
        d.setVisible(true);
    }

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

            @Override
            public void run() {
                new Test().display();
            }
        });
    }

    private static class ImagePanel extends JPanel {

        private static final int MASK
            = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
        private JFileChooser chooser = new JFileChooser();
        private Action openAction = new ImageOpenAction("Open");
        private Action clearAction = new ClearAction("Clear");
        private JMenuBar menuBar = new JMenuBar();
        private JPopupMenu popup = new JPopupMenu();
        private BufferedImage image;

        public ImagePanel() {
            this.setComponentPopupMenu(popup);
            popup.add("Popup Menu");
            popup.add(new JMenuItem(openAction));
            popup.add(new JMenuItem(clearAction));
            JMenu menu = new JMenu("File");
            menu.setMnemonic('F');
            menu.add(new JMenuItem(openAction));
            menu.add(new JMenuItem(clearAction));
            menuBar.add(menu);
        }

        @Override
        public Dimension getPreferredSize() {
            if (image == null) {
                return new Dimension(320, 240);
            } else {
                return new Dimension(image.getWidth(), image.getHeight());
            }
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(image, 0, 0, null);
        }

        private class ClearAction extends AbstractAction {

            public ClearAction(String name) {
                super(name);
                this.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_C);
                this.putValue(Action.ACCELERATOR_KEY,
                    KeyStroke.getKeyStroke(KeyEvent.VK_C, MASK));
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                image = null;
                revalidate();
                repaint();
            }
        }

        private class ImageOpenAction extends AbstractAction {

            public ImageOpenAction(String name) {
                super(name);
                this.putValue(Action.MNEMONIC_KEY, KeyEvent.VK_O);
                this.putValue(Action.ACCELERATOR_KEY,
                    KeyStroke.getKeyStroke(KeyEvent.VK_O, MASK));
            }

            @Override
            public void actionPerformed(ActionEvent e) {
                int returnVal = chooser.showOpenDialog(chooser);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    File f = chooser.getSelectedFile();
                    try {
                        image = ImageIO.read(f);
                        revalidate();
                        repaint();
                    } catch (IOException ex) {
                        ex.printStackTrace(System.err);
                    }
                }
            }
        }
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045