javaswingjtextfieldfocuslistener

Generalize several text fields for selecting the entire text when focus is gained


I want each of several text fields in a panel to have center alignment and to have a focus listener that will select the entire field when focus is gained.

txtSelection = new JTextField("", 9);
txtInclusion = new JTextField("", 9);
txtExclusion = new JTextField("", 9);
...

I know how to do it one by one:

txtSelection.setHorizontalAlignment(JTextField.CENTER);

txtSelection.addFocusListener(new FocusAdapter() {

  public void focusGained(FocusEvent e) {

    txtSelection.select(0, 9);
  }
});

But I'd rather not repeat that structure for all the text fields.

I tried this (and a couple of varieties) but the code seems to do nothing:

pnlConditions = new JPanel();
pnlConditions.setLayout(new GridBagLayout());

for(final Component c : pnlConditions.getComponents())  // compiler insisted on 'final'
{
  ((JTextField)c).setHorizontalAlignment(JTextField.CENTER);

  if(c instanceof JTextField)
  {
    c.addFocusListener
      (new FocusAdapter()
        {
          @Override public void focusGained(FocusEvent e) 
          {
            ((JTextField)c).select(0,9);   // compiler suggested cast to JTextComponent; no difference
          }
        }
      );
  }
}

The entire field is not selected; alignment is left (the default). I guess my first clues that it wouldn't work are the compiler's insisting that c must be final in the for and for suggesting that the cast should have been to JTextComponent in the statement with select; but it didn't make that suggestion on the statement with setHorizontal....

I'm sure this can be done; but how?


Here's the entire method containing the snippets above:

  static void makePnlConditions(){
    JLabel lblSelections = new JLabel("Select ONLY combos with ALL of:");
    JLabel lblInclusions = new JLabel("DE-select combo NOT containing one or more of:");
    JLabel lblExclusions = new JLabel("DE-select combo containing ANY of:");

    txtSelection = new JTextField("", 9);
    txtInclusion = new JTextField("", 9);
    txtExclusion = new JTextField("", 9);

    pnlConditions = new JPanel();
    pnlConditions.setLayout(new GridBagLayout());

    for(final Component c : pnlConditions.getComponents())
    {
      ((JTextField)c).setHorizontalAlignment(JTextField.CENTER);

      if(c instanceof JTextField)
      {
        c.addFocusListener
          (new FocusAdapter()
            {
              @Override public void focusGained(FocusEvent e) 
              {
                ((JTextField)c).select(0,9);
              }
            }
          );
      }
    }

    pnlConditions.add(lblSelections);
    pnlConditions.add(txtSelection);
    pnlConditions.add(lblInclusions);
    pnlConditions.add(txtInclusion);
    pnlConditions.add(lblExclusions);
    pnlConditions.add(txtExclusion);
  }

Solution

  • First add the components into JPanel otherwise pnlConditions.getComponents() will return an empty array and no listener will be added for JTextField.

    If you want to select entire text then use JTextComponent#selectAll() method.

    Sample code:

    JPanel pnlConditions = new JPanel();
    pnlConditions.setLayout(new GridBagLayout());
    
    pnlConditions.add(lblSelections);
    pnlConditions.add(txtSelection);
    pnlConditions.add(lblInclusions);
    pnlConditions.add(txtInclusion);
    pnlConditions.add(lblExclusions);
    pnlConditions.add(txtExclusion);
    
    for (final Component c : pnlConditions.getComponents()) {      
        if (c instanceof JTextField) {
            ((JTextField) c).setHorizontalAlignment(JTextField.CENTER);
            ...
        }
    }
    

    I want each of several text fields in a panel to have center alignment and to have a focus listener that will select the entire field when focus is gained.

    Create a custom class that extends JTextField, provide all default implementation and use it everywhere in your application to make it centralized.

    Sample code:

    class MyJTextField extends JTextField {
    
        // Initialization block that is called for all the constructors
        {
            this.addFocusListener(new FocusAdapter() {
                @Override
                public void focusGained(FocusEvent e) {
                    selectAll();
                }
            });
            this.setHorizontalAlignment(JTextField.CENTER);
        }
    
        public MyJTextField() {}
        public MyJTextField(String text) {super(text);}
        public MyJTextField(int columns) {super(columns);}
        public MyJTextField(String text, int columns) {super(text, columns);}
    }