JDK-6515446 : JMenuItems in JPopupMenus not receiving ActionEvents - incompat with 1.5
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-01-19
  • Updated: 2011-01-19
  • Resolved: 2007-04-12
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u2 b02Fixed 7Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
JMenuItems in JPopupMenus do not seem to be receiving ActionEvents when the mouse button is released over the item.  This is incompatible with 1.5.0_10, in which an ActionEvent is received..

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the attached program.  Right or left click in the middle of the frame. Select the item from the popup that appears.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The button text should be displayed in the lower left corner.  This is what happens under 1.5.0_10.
ACTUAL -
The text is not displayed under 1.6.0.

Note that if you select the item from the menu in the menu bar, the text is always displayed under both versions.  It is only with popups that the anomaly occurs.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.*;

import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JMenuBar;
import javax.swing.JPopupMenu;
import javax.swing.JPanel;
import javax.swing.JFrame;

public class PopupDemo extends JPanel implements ActionListener, MouseListener {
   private static final long serialVersionUID = 1L;
   JPopupMenu popup = new JPopupMenu();
   JLabel messageArea = new JLabel();

   public static void main(String[] args) {
      new PopupDemo();
   }

   public PopupDemo() {
      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      JMenuBar menuBar = new JMenuBar();
      JMenu menu = new JMenu("menu");
      menuBar.add(menu);
      JMenuItem menuItem = new JMenuItem("menu item");
      menuItem.addActionListener(this);
      menu.add(menuItem);
      
      menuItem = new JMenuItem("popup item");
      menuItem.addActionListener(this);
      popup.add(menuItem);
      
      addMouseListener(this);
      setPreferredSize(new Dimension(200, 200));
      frame.setJMenuBar(menuBar);
      frame.add(this,BorderLayout.CENTER);
      frame.add(messageArea,BorderLayout.SOUTH);
      frame.pack();
      frame.setLocation(200, 200);
      frame.setVisible(true);
   }

   public void actionPerformed(ActionEvent e) {
      messageArea.setText(e.getActionCommand());
   }
   public void mousePressed(MouseEvent e) {
      messageArea.setText("");
      popup.show(this,e.getX(),e.getY());
   }
   public void mouseReleased(MouseEvent e) {
      popup.setVisible(false);
   }
   public void mouseClicked(MouseEvent e) {}
   public void mouseEntered(MouseEvent e) {}
   public void mouseExited(MouseEvent e) {}
}

---------- END SOURCE ----------

Release Regression From : 5
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Release Regression From : 5
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
EVALUATION After thoroughly testing it becomes clear that this is a serious bug and we should fix it ASAP I tested this testcase together with ones from 6415145 and 5036146 and think it is possible to fix this one without breaking the others the idea is to add the if (isInPopup(src)) { break; } checking to the MouseEvent.MOUSE_RELEASED: case of the MouseGrabber, it is actually the same what we have already done for the MOUSE_DRAGGED case More testing will be done
21-03-2007

WORK AROUND another workaround is to make a panel implement MenuElement interface with just empty methods
20-03-2007

EVALUATION This is a side-effect of the fix for 5036146 which skips the mouseReleased events for a menu if invoker is not a MenuElement (see the suggested fix) I am not sure it is possible to fix this regressing without breaking the fix for the 5036146
12-03-2007

WORK AROUND Calculate the location of the popup menu and call action performed from the mouseRelease if mouse cursor is released within the popup menu area. import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dimension; import java.awt.Point; import java.awt.event.*; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JMenuBar; import javax.swing.JPopupMenu; import javax.swing.JPanel; import javax.swing.JFrame; public class PopupDemo extends JPanel implements ActionListener, MouseListener { private static final long serialVersionUID = 1L; JPopupMenu popup = new JPopupMenu(); JLabel messageArea = new JLabel(); public static void main(String[] args) { new PopupDemo(); } public PopupDemo() { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JMenuBar menuBar = new JMenuBar(); JMenu menu = new JMenu("menu"); menuBar.add(menu); JMenuItem menuItem = new JMenuItem("menu item"); menuItem.addActionListener(this); menu.add(menuItem); PopupMenuItem popupMenuItem = new PopupMenuItem("popup item 1"); popupMenuItem.addActionListener(this); popup.add(popupMenuItem); popupMenuItem = new PopupMenuItem("popup item 2"); popupMenuItem.addActionListener(this); popup.add(popupMenuItem); popupMenuItem = new PopupMenuItem("popup item 3"); popupMenuItem.addActionListener(this); popup.add(popupMenuItem); addMouseListener(this); setPreferredSize(new Dimension(200, 200)); frame.setJMenuBar(menuBar); frame.add(this,BorderLayout.CENTER); frame.add(messageArea,BorderLayout.SOUTH); frame.pack(); frame.setLocation(200, 200); frame.setVisible(true); } Point popupLoc; public void actionPerformed(ActionEvent e) { messageArea.setText(e.getActionCommand()); } public void mousePressed(MouseEvent e) { messageArea.setText(""); popupLoc = new Point(e.getX(), e.getY()); popup.show(this, e.getX(), e.getY()); } public void mouseReleased(MouseEvent e) { Component[] popupMenuItems = popup.getComponents(); for (Component c : popupMenuItems) { Point itemLoc = c.getLocation(); if (c.contains(e.getX() - itemLoc.x - popupLoc.x, e.getY() - itemLoc.y - popupLoc.y)) { ((PopupMenuItem)c).fireActionPerformed(); break; } } popup.setVisible(false); } public void mouseClicked(MouseEvent e) {} public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} } class PopupMenuItem extends JMenuItem { private static final long serialVersionUID = 1L; public PopupMenuItem(String text) { super(text); } public void fireActionPerformed() { fireActionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, getActionCommand())); } }
26-01-2007