Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 913
guitar_freak Avatar asked Feb 16 '23 19:02

guitar_freak


1 Answers

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)
like image 58
kleopatra Avatar answered Feb 27 '23 11:02

kleopatra