FULL PRODUCT VERSION : java version "1.8.0_60" Java(TM) SE Runtime Environment (build 1.8.0_60-b27) Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows [Version 6.1.7601] A DESCRIPTION OF THE PROBLEM : Focus switches from the focussed component to two components further in the focus chain when a dialog is opened and closed before it received focus itself. It seems to go wrong because java.awt.Component#7663: A component registers itself as mostRecentFocusOwner java.awt.Component#7703: The component requests focus (this fails in the reproduction) Is done in combination with: java.awt.DefaultKeyboardFocusManager:doRestoreFocus(Window, Component, Boolean): trying to focus the MostRecentFocusOwner and then the next one STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1) Run the attached source 2) Press Enter in any of the textfields A dialog opens and closes immediately. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - The focused component should still be the textfield that was focused when pressing Enter. ACTUAL - The focus switches from the original field to the field that is 2 components further in the focus chain. REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JTextField; import javax.swing.WindowConstants; public class FocusBug extends JFrame implements ActionListener { private final SimpleDialog mDialog = new SimpleDialog(); public static void main(String[] args) { FocusBug tfs = new FocusBug(); tfs.setVisible(true); } public FocusBug() { setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); Container c = getContentPane(); c.setLayout(new FlowLayout()); for (int i = 0; i < 10; i++) { JTextField tf = new JTextField(10); c.add(tf); tf.addActionListener(this); } pack(); } @Override public void actionPerformed(ActionEvent e) { mDialog.showQuickly(); } private static class SimpleDialog extends JDialog { public void showQuickly() { setVisible(true); setVisible(false); } } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : It is possible to add a WindowFocusListener to the dialog that waits until the setVisible(false) is called _and_ it has received focus. If one of the two is called it should wait before actually calling super.setVisible(false).
|