JDK-5018574 : Unable to set focus to another component in JOptionPane
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0,5.0u18
  • Priority: P2
  • Status: Closed
  • Resolution: Won't Fix
  • OS: generic
  • CPU: generic,x86
  • Submitted: 2004-03-23
  • Updated: 2009-09-23
  • Resolved: 2009-09-04
Description

Name: dmR10075			Date: 03/23/2004


If JOptionPane is used to create input dialog using a static method,
and as a message some JComponent is provided, there is no way to
set focus to this component upon JOptionPane showing. It always sets
focus to default button. 

I think it is an overkill - default button will anyway be pressed if
user presses Enter, but the focus should instead go to the default
component in a Window. To implement this, JOptionPane just shouldn't
request focus at all and focus subsystem will do the rest. As an option,
JOptionPane can modify focus traversal policy to indicate that default
button is in fact default focus component.

Another possibility might be to request focus to default button(if it is
still necessary, for example, for some L&F), but do this BEFORE message
is added so that there is a way to request focus to the user's component
on some event(SHOWING, for example) after the request to default button.

If any workaround is possible, please indicate that.

Below is the test case:
import javax.swing.*;
import java.awt.FlowLayout;

public class JOptionPaneFocus {
    public static void main(String[] args) {
        JPanel panel = new JPanel();
        JButton button = new JButton("Focus");
        panel.setLayout(new FlowLayout());
        panel.add(button);
        JOptionPane.showOptionDialog(null,
                                     panel, 
                                     "Check focus",
                                     JOptionPane.OK_CANCEL_OPTION,
                                     JOptionPane.PLAIN_MESSAGE,
                                     null, null, null);
    }
}

======================================================================

Comments
EVALUATION We had a discussion with AWT engineers regarding this issue, and came to a conclusion that this bug is very difficult for fixing. When JOptionPane is shown, the default button gets focused. There is no API to change the focused component in advance. Focus implementation in AWT/Swing is asynchronous, so the simple requesting focus to a component doesn't work, because it gets overridden by the next requesting focus to the default button. Trying to fix this CR would lead to modifying existing API or introducing a new one, which would mean making big changes in AWT code base. This may affect product stability. Because of it and also because of workaround availability, I'm closing this CR with "Will Not Fix" status.
04-09-2009

WORK AROUND This workaround didn't work as expected. For a good workaround, see the comment from 2009-08-18 in Evaluation section and TestJoptionPane.java in Attachments.
25-08-2009

EVALUATION The following workaround solves the issue. JPanel panel = new JPanel(); JButton button = new JButton("Focus"); panel.setLayout(new FlowLayout()); panel.add(button); // begin workaround button.addHierarchyListener(new HierarchyListener() { public void hierarchyChanged(HierarchyEvent e) { final Component c = e.getComponent(); if (c.isShowing() && (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { Window toplevel = SwingUtilities.getWindowAncestor(c); toplevel.addWindowFocusListener(new WindowAdapter() { public void windowGainedFocus(WindowEvent e) { c.requestFocus(); } }); } } }); // end workaround JOptionPane.showOptionDialog(null, panel, "Check focus", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null); You can find a full example in attachments - TestJoptionPane.java.
18-08-2009

EVALUATION workaround provided
29-06-2009

WORK AROUND public static void main(String[] args) { JPanel panel = new JPanel(); JButton button = new JButton("Focus"); panel.setLayout(new FlowLayout()); panel.add(button); // begin workaround button.addHierarchyListener(new HierarchyListener() { public void hierarchyChanged(HierarchyEvent e) { final Component c = e.getComponent(); if (c.isShowing() && (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) { SwingUtilities.invokeLater(new Runnable() { public void run() { c.requestFocus(); } }); } } }); // end workaround JOptionPane.showOptionDialog(null, panel, "Check focus", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null); }
29-06-2009

EVALUATION Agreed, I can see how this behavior could be rather frustrating. This will likely require an API change. ###@###.### 2004-03-31
31-03-2004