I am experimenting on capturing all the mouse events and based on some logic dispatch them to the related components. The capturing occurs with the use of a glasspane which captures all mouse events and then I calculate the component that should be underneath the glasspane to dispatch the event to it. This works okay for buttons but is impossible to work for JPopupmenus, not sure why I tried different approaches but couldn't get the reference of the JPopupmenu or once of its items.
Here is a minimum working example, click on the button and see that it works okay click on the jpopupmenu that was displayed from prev step and notice that the jpanel is clicked.
public class GlassPaneExample2 {
public static void main(String[] args) {
JFrame frame = new JFrame("Glass Pane Example");
frame.setSize(400, 300);
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
JButton button = new JButton("Button 2 txt");
button.addActionListener(e -> showPopupMenu(button));
mainPanel.add(button, BorderLayout.LINE_START);
frame.add(mainPanel);
GlassPane glassPane = new GlassPane(frame.getContentPane());
frame.setGlassPane(glassPane);
glassPane.setVisible(true);
frame.setVisible(true);
}
private static void showPopupMenu(Container container) {
JPopupMenu jPopupMenu = new JPopupMenu();
JMenuItem menuItem1 = new JMenuItem("Menu Item 1");
JMenuItem menuItem2 = new JMenuItem("Menu Item 2");
menuItem1.addActionListener(e -> JOptionPane.showMessageDialog(container, "Menu Item 1 selected"));
menuItem2.addActionListener(e -> JOptionPane.showMessageDialog(container, "Menu Item 2 selected"));
jPopupMenu.add(menuItem1);
jPopupMenu.add(menuItem2);
jPopupMenu.show(container, 100, 10);
}
}
class GlassPane extends JComponent {
static Component findComponentUnderGlassPane(JComponent glassPane, Point glassPaneEventPoint, Container contentPane) {
Point containerPoint = SwingUtilities.convertPoint(glassPane, glassPaneEventPoint, contentPane);
if (containerPoint.y >= 0) {
return SwingUtilities.getDeepestComponentAt(contentPane, containerPoint.x, containerPoint.y);
}
return null;
}
void dispatch(MouseEvent mouseEvent, Container container) {
EventQueue.invokeLater(() -> {
Component component = findComponentUnderGlassPane(GlassPane.this, mouseEvent.getPoint(), container);
if (component != null && !component.equals(GlassPane.this)) {
System.out.println("Dispatching to " + component.getClass().getSimpleName() + "#" + component.hashCode());
component.dispatchEvent(SwingUtilities.convertMouseEvent(GlassPane.this, mouseEvent, component));
}
});
}
public GlassPane(Container contentPane) {
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e){
dispatch(e, contentPane);
}
@Override
public void mouseReleased(MouseEvent e){
dispatch(e, contentPane);
}
@Override
public void mouseClicked(MouseEvent e) {
dispatch(e, contentPane);
}
@Override
public void mouseEntered(MouseEvent e) {
dispatch(e, contentPane);
}
@Override
public void mouseExited(MouseEvent e) {
dispatch(e, contentPane);
}
@Override
public void mouseMoved(MouseEvent e) {
dispatch(e, contentPane);
}
@Override
public void mouseDragged(MouseEvent e) {
dispatch(e, contentPane);
}
});
}
}