Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
FULL PRODUCT VERSION : java version "1.6.0-rc" Java(TM) SE Runtime Environment (build 1.6.0-rc-b104) Java HotSpot(TM) 64-Bit Server VM (build 1.6.0-rc-b104, mixed mode) ADDITIONAL OS VERSION INFORMATION : Linux muellerp02linux 2.6.11.4-20a-smp #1 SMP Wed Mar 23 21:52:37 UTC 2005 x86_64 x86_64 x86_64 GNU/Linux EXTRA RELEVANT SYSTEM CONFIGURATION : This also happens on 32-bit Linux A DESCRIPTION OF THE PROBLEM : When a menu item is triggered via a mnemonic the corresponding character ends up appearing in the text component that had focus before the menu was activated. This only happens when the text component has a heavyweight ancestor other than the frame itself. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1. Run the attached HeavyMnemonicProblem class on Linux 2. Select the File menu 3. Invoke the Test menu item by pressing its mnemonic 't'. 4. Observe that the character 't' appears in the text area. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - No character should appear in the text component as a result of triggering a menu item using its mnemonic ACTUAL - The mnemonic character both triggers the menu item and appears in the text component REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.awt.*; import java.awt.event.*; import javax.swing.*; public class HeavyMnemonicProblem { public static void main(String[] args) { JPopupMenu.setDefaultLightWeightPopupEnabled(false); JFrame frame = new JFrame("Heavyweight/Mnemonic Problem"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Add a heavyweight panel containing a lightweigth MJTextArea to the frame's // content pane. Panel heavyPanel = new Panel(new BorderLayout()); JTextArea textArea = new JTextArea(); heavyPanel.add(textArea, BorderLayout.CENTER); frame.getContentPane().add(heavyPanel); // Add a menu bar with a mnemonic JMenuBar bar = new JMenuBar(); JMenu menu = new JMenu("File"); menu.setMnemonic('F'); JMenuItem item = new JMenuItem("Test"); item.setMnemonic('T'); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("Test"); } }); menu.add(item); bar.add(menu); frame.setJMenuBar(bar); // Add an AWTEventListener for diagnostics AWTEventListener awtListener = new AWTEventListener() { public void eventDispatched(AWTEvent event) { System.out.print(event.paramString()); System.out.println(" on " + event.getSource().getClass().getName()); } }; Toolkit.getDefaultToolkit().addAWTEventListener(awtListener, AWTEvent.KEY_EVENT_MASK); frame.setBounds(100, 100, 400, 300); frame.setVisible(true); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : The problem can be prevented by using a KeyEventDispatcher to detect and discard key typed events for a component other than the root pane when the preceeding key pressed event was on the root pane. The following code does this: KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(new StrayKeyTypedSuppressor()); static class StrayKeyTypedSuppressor implements KeyEventDispatcher { private Component sPressedComponent; public boolean dispatchKeyEvent(KeyEvent event) { if (event.getID() == KeyEvent.KEY_PRESSED) { if (event.getComponent() instanceof JRootPane) sPressedComponent = event.getComponent(); } else { if (event.getID() == KeyEvent.KEY_TYPED && sPressedComponent != null && sPressedComponent != event.getComponent()) return true; sPressedComponent = null; } return false; } }
|