Note that there are some explanatory texts on larger screens.

plurals
  1. POJava LostFocus and InputVerifier, moving in reverse-tab-order
    text
    copied!<p>I have a GUI application that uses an InputVerifier to check the content of text fields before yielding the focus. This is all very normal. Yesterday, however, discovered a problem - it seems to be a bug, but I cannot find any mention of it anywhere. Before I report this as a bug, I thought I would ask: am I missing something obvious here?</p> <p>Situation:</p> <ul> <li>A set of text fields with InputVerifiers.</li> <li>Listeners for FocusLost and FocusGained on all controls, so I can see what is happening.</li> <li>A separate thread uses a DefaultKeyboardFocusManager to report (every 2 seconds) which control has the focus.</li> <li>I place invalid data in a JTextField in the middle of the form, and try to leave the control.</li> </ul> <p>If I try to move away from this control using the mouse, or using the tab-key, I cannot. The FocusLost event does not fire and the control properly retains the focus.</p> <p>However, if I try to move away from the control <i>in reverse tab order, using Shift-Tab</i>, <b>sometimes</b> the FocusLost event fires. If this happens, the separate thread reports that <b>no control has the focus</b>, i.e., getFocusOwner() returns null. <hr> Edit: below is a small sample program that shows the problem. The problem has nothing to do with the extra thread - the thread is just there to make the problem more obvious. If there is a race-condition, it is somewhere in Swing.</p> <p>To see the problem, go to the second text box and empty it. The control should retain the focus, and does so <em>unless</em> you leave it by pressing shift-tab. Unlike the full application, the error seems to occur here 100% of the time. This is true both under OpenJDK 6 and under Oracle Java 7.</p> <p>This is almost too obvious to be a bug, plus it happens in multiple Java environments. Hence, my suspicion that I am missing something obvious. Anyone?</p> <pre><code>public class FocusBugDemo extends JFrame { static JTextField txtOne = new JTextField("Ignore this control"); static JTextField txtTwo = new JTextField("Delete this text, then press shift-tab"); static JLabel lblFocus = new JLabel(""); static KeyboardFocusManager kfm = new DefaultKeyboardFocusManager(); public static void main(String[] args) { new FocusBugDemo(); Thread t = new Thread() { @Override public void run() { while(true) { Component c = kfm.getFocusOwner(); String focusInfo = "elsewhere"; if (c == null) { focusInfo = "null"; } else if (c == txtOne) { focusInfo = "txtOne"; } else if (c == txtTwo) { focusInfo = "txtTwo"; } lblFocus.setText(System.currentTimeMillis() + " - Focus owner " + focusInfo); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } }; t.start(); } private FocusBugDemo() { super("Focus bug demo"); setDefaultCloseOperation(EXIT_ON_CLOSE); setPreferredSize(new Dimension(300,100)); setLayout(new GridLayout(3,1)); NotEmpty validator = new NotEmpty(); txtOne.setInputVerifier(validator); txtTwo.setInputVerifier(validator); add(txtOne); add(txtTwo); add(lblFocus); pack(); setVisible(true); } private class NotEmpty extends InputVerifier { @Override public boolean verify(JComponent input) { JTextField txtField = (JTextField) input; return (txtField.getText().length() &gt; 0); } } } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload