Apply focus to component

0

I have a component that is a JPanel that contains two JTextFields , I wanted to be able to apply borders and backgrounds only to the JTextFields , without applying it in the panel.

I treat everything on the main screen to be applied to everything that is of type JComponent , and also because the component can be applied to multiple screens.

For other components like JTextFields and JTextArea , it applies correctly.

Simplified example:

package focu;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;

public class TelaPrincipal extends JFrame implements FocusListener {

    private JLabel label = new JLabel("Componente:");
    private MeuComponente comp = new MeuComponente();
    private JLabel label2 = new JLabel("JTextField:");
    JTextField jt = new JTextField();
    private JLabel label3 = new JLabel("JTextArea:");
    JTextArea area = new JTextArea();

    public static void main(String[] args) {
        TelaPrincipal teste = new TelaPrincipal();
        teste.setVisible(true);
    }

    public TelaPrincipal() {
        setTitle("Teste");
        add(montaTela());
        //setSize(150, 300);
        pack();
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }

    private JComponent montaTela() {
        JPanel painel = new JPanel();
        painel.setLayout(new FlowLayout());

        painel.add(label);
        painel.add(comp);
        comp.addFocusListener(this);

        painel.add(label2);
        painel.add(jt);
        jt.setPreferredSize(new Dimension(100, 20));
        jt.addFocusListener(this);

        painel.add(label3);
        painel.add(area);
        area.setPreferredSize(new Dimension(100, 100));
        area.addFocusListener(this);

        return painel;
    }

    @Override
    public void focusGained(FocusEvent fe) {
        if (fe.getSource() instanceof JComponent) {
            ((JComponent) fe.getSource()).setBorder(new LineBorder(Color.RED));
            ((JComponent) fe.getSource()).setBackground(Color.LIGHT_GRAY);
        }
    }

    @Override
    public void focusLost(FocusEvent e) {
        ((JComponent) e.getSource()).setBorder(new LineBorder(Color.GRAY));
        ((JComponent) e.getSource()).setBackground(Color.WHITE);
    }
}

class MeuComponente extends JPanel
{
    public JTextField jt01 = new JTextField();
    public JTextField jt02 = new JTextField();

    public MeuComponente()
    {
        setLayout(new FlowLayout());
        add(jt01);
        jt01.setPreferredSize(new Dimension(70, 20));    
        add(jt02);
        jt02.setPreferredSize(new Dimension(70, 20));
    }
}
    
asked by anonymous 21.06.2017 / 05:11

1 answer

4

FocusListener should not be applied to top-level components as JFrame . If the goal was to control the focus of the screen, you should use WindowListener .

But since the goal, at least as I understand it, is to change component characteristics, the focus must be applied to each one individually, because the focus is not something shared. To do this, you need to scan all the components of the screen and, if these components are containers, also scan the internal components.

To make this more automated and flexible to the additions of new on-screen components, you can redeem a list of all components through the #

private void setFocusInComponents(Container container) {

    Component[] components = container.getComponents();

    for (Component comp : components) {

        if (comp instanceof Container) {
            setFocusInComponents((Container) comp);
        }

        comp.addFocusListener(new FocusListener() {

            @Override
            public void focusLost(FocusEvent e) {
                // TODO Auto-generated method stub
                JComponent comp = (JComponent) e.getSource();

                comp.setBorder(new LineBorder(Color.GRAY));
                comp.setBackground(Color.WHITE);

            }

            @Override
            public void focusGained(FocusEvent e) {
                // TODO Auto-generated method stub
                JComponent comp = (JComponent) e.getSource();

                comp.setBorder(new LineBorder(Color.RED));
                comp.setBackground(Color.LIGHT_GRAY);

            }
        });
    }
}

To use the method in your code, just call getComponents() after adding all components in setFocusInComponents() , passing the JFrame method as parameter, since this method returns the panel that holds everything that is added in getcontentPane() .

setFocusInComponents(this.getContentPane());

It's always a good idea to remember that swing applications should always be started within the specified Thread for her .

    
21.06.2017 / 13:58