Azuu
Azuu

Reputation: 856

Getting the Component which has Focus in java

I have JFrame which is having multiple Panels on it. Each Panel is having some Components designed on that. I want to Change the Background Color of Component(JTextField) when it gain Focus. I have Many TextFields and I dont want to Write FocusListener for all the Components. Is there any solution to do it in a Smart Manner.

Upvotes: 2

Views: 4214

Answers (4)

MadProgrammer
MadProgrammer

Reputation: 347334

You could attach a ProperyChangeListener to the KeyboardFocusManager @ monitor the appropriate changes

Upvotes: 1

Roland Schneider
Roland Schneider

Reputation: 3635

Another way would be to write your own TextFieldUI which implements the Listener. However, the factory approach is much more elegant.

Example:

import java.awt.Color;
import java.awt.EventQueue;
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.JTextField;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.metal.MetalTextFieldUI;

public class CustomUI extends JFrame {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            public void run() {
                UIManager.getDefaults().put("TextFieldUI", CustomTextFieldUI.class.getName());
                new CustomUI().setVisible(true);
            }

        });
    }

    public CustomUI() {
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setLayout(new FlowLayout());
        add(new JTextField(10));
        add(new JTextField(10));
        pack();
    }

    public static class CustomTextFieldUI extends MetalTextFieldUI implements FocusListener {

        public static ComponentUI createUI(JComponent c) {
            return new CustomTextFieldUI();
        }

        @Override
        public void installUI(JComponent c) {
            super.installUI(c);
            c.addFocusListener(this);
        }

        public void focusGained(FocusEvent e) {
            getComponent().setBackground(Color.YELLOW.brighter());
        }

        public void focusLost(FocusEvent e) {
            getComponent().setBackground(UIManager.getColor("TextField.background"));
        }

    }

}

Upvotes: 2

kleopatra
kleopatra

Reputation: 51535

You should definitely consider your design, as suggested by @Robin. Creating and configuring all components of an application through a factory helps to make it robust against requirement changes as there is a single location to change instead of being scattered all over the code.

Moreover, an individual listener per component keeps the control near-by to where the focus induced property changes occur, thus not needing state handling in a global listener.

That said, the technical (as in: use with care!) solution for a global focusListener is to register a propertyChangeListener with the KeyboardFocusManager.

A quick code snippet (with very crude state handling :-)

JComponent comp = new JPanel();
for (int i = 0; i < 10; i++) {
    comp.add(new JTextField(5));
}
PropertyChangeListener l = new PropertyChangeListener() {
    Component owner;
    Color background;
    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (owner != null && evt.getOldValue() == owner) {
            owner.setBackground(background);
            owner = null;
        } 
        if (evt.getNewValue() != null) {
            owner = (Component) evt.getNewValue();
            background = owner.getBackground();
            owner.setBackground(Color.YELLOW);
        }
    }
};
KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener("permanentFocusOwner", l);

Upvotes: 10

Robin
Robin

Reputation: 36621

I dont want to Write FocusListener for all the Components

So you do not want to replace your

JTextField textField = new JTextField();

by

JTextField textField = TextFieldFactory.createTextField();

where TextFieldFactory#createTextField is a utility method which creates a JTextField with the desired functionality. Care to elaborate on that ?

Upvotes: 6

Related Questions