2

複数のパネルがあるJFrameがあります。各パネルには、その上に設計されたいくつかのコンポーネントがあります。コンポーネント(JTextField)がフォーカスを取得したときに背景色を変更したい。多くのTextFieldがあり、すべてのコンポーネントにFocusListenerを記述したくありません。スマートマナーでそれを行うための解決策はありますか?

4

4 に答える 4

10

@Robin が提案しているように、必ずデザインを検討する必要があります。ファクトリを使用してアプリケーションのすべてのコンポーネントを作成および構成すると、コード全体に分散するのではなく、変更する場所が 1 か所になるため、要件の変更に対して堅牢になります。

さらに、コンポーネントごとの個々のリスナーは、フォーカスによって引き起こされるプロパティの変更が発生する場所の近くにコントロールを保持するため、グローバル リスナーで状態を処理する必要はありません。

とは言っても、グローバル focusListener の技術的な (慎重に使用するように!) 解決策は、propertyChangeListener を KeyboardFocusManager に登録することです。

簡単なコード スニペット (非常に大雑把な状態処理を含む :-)

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);
于 2012-07-23T13:00:37.040 に答える
6

すべてのコンポーネントに対して FocusListener を書きたくない

だからあなたはあなたを交換したくない

JTextField textField = new JTextField();

JTextField textField = TextFieldFactory.createTextField();

whereは、目的の機能を備えたTextFieldFactory#createTextFieldを作成するユーティリティ メソッドです。JTextFieldそれについて詳しく説明しますか?

于 2012-07-23T12:23:56.900 に答える
2

TextFieldUI別の方法は、リスナーを実装する独自の方法を作成することです。ただし、ファクトリアプローチははるかにエレガントです。

例:

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"));
        }

    }

}
于 2012-07-23T13:10:04.787 に答える
1

ProperyChangeListenerあなたはKeyboardFocusManagerにアタッチすることができます@適切な変更を監視します

于 2012-07-23T14:42:28.857 に答える