radekEm
radekEm

Reputation: 4647

Java Swing - JDialog default focus

I have found in the Internet such an info:

"When a JDialog (or JFrame for that matter) is made visible, focus is placed on the first focusable component by default."

Let's consider such a code:

public class MyDialog extends JDialog{
    // Dialog's components:
    private JLabel dialogLabel1 = new JLabel("Hello");
    private JLabel dialogLabel2 = new JLabel("Message");
    private JButton dialogBtn = new JButton("Sample Btn text");

    public MyDialog(JFrame parent, String title, ModalityType modality){
        super(parent, title, modality);
        dialogBtn.setName("Button");    //
        dialogLabel1.setName("Label1"); // - setting names
        dialogLabel2.setName("Label2"); //
        setTitle(title);
        setModalityType(modality);
        setSize(300, 100);
        setLocation(200, 200);
        // adding comps to contentPane
        getContentPane().add(dialogLabel1, BorderLayout.PAGE_START);
        getContentPane().add(dialogBtn, BorderLayout.CENTER);
        getContentPane().add(dialogLabel2, BorderLayout.PAGE_END);
        pack();
    }

    public void showDialog(){
        setVisible(true);
        listComps(rootPane.getComponents());
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }

    /*
     * Itereates through all subcomps recursively and displays some relevant info
     * OUTPUT FORM:  ComponentName | isFocusable | hasFocus
     */
    private void listComps(Component[] comps){
        if(comps.length == 0) return;  
        for(Component c : comps){       
            JComponent jC = (JComponent)c;
            System.out.println(jC.getName() + " | " + jC.isFocusable() +" | " + jC.hasFocus());
            listComps(jC.getComponents());
        }    
    }

    public static void main(String[] args) {
        final JFrame frame = new JFrame();
        frame.setPreferredSize(new Dimension(300, 400));
        frame.setVisible(true);
        JButton btn = new JButton("Show dialog");
        btn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                    MyDialog dialog = new MyDialog(frame, "Sample title", ModalityType.APPLICATION_MODAL);
                    dialog.showDialog();
            }
        });
        frame.add(btn, BorderLayout.CENTER);
        frame.pack();
    }
}

Output is: run:

null.glassPane | true | false
null.layeredPane | true | false
null.contentPane | true | false
Label1 | true | false
Button | true | true
Label2 | true | false

Why focus is set to the JButton?? It is not the first focusable component! When I've removed JButton, focus wasn't gained to any component. Why? All compos are focusable by default...

Upvotes: 4

Views: 3771

Answers (2)

kleopatra
kleopatra

Reputation: 51524

It is not the first focusable component! When I've removed JButton, focus wasn't gained to any component. Why? All compos are focusable by default.

To answer the why: it's the decision of the FocusTraversalPolicy, particularly the accept(..) in DefaultFocusTraversalPolicy which ultimately falls back to the dummy NullComponentPeer (which is not focusable by default, as it doesn't really exist :-)

From your comment, it looks like the real question might be "how to implement keyBindings if the rootPane has no focusable children" - if so, the options are

  • use the rootPane's componentInputMap, that is WHEN_IN_FOCUSED_WINDOW
  • force the rootPane itself into focusable (probably best doing this only if there are no focusable children)

Upvotes: 6

mael
mael

Reputation: 2254

Take a look at the JLabel javadoc It says:

A display area for a short text string or an image, or both. A label does not react to input events. As a result, it cannot get the keyboard focus

I think this is the reason why your label does not get the focus.

Upvotes: 2

Related Questions