【发布时间】:2012-07-21 16:23:00
【问题描述】:
我有 JFrame,上面有多个面板。每个面板都有一些在此基础上设计的组件。我想在获得焦点时更改组件(JTextField)的背景颜色。 我有很多 TextField,我不想为所有组件编写 FocusListener。 有没有办法以聪明的方式做到这一点。
【问题讨论】:
我有 JFrame,上面有多个面板。每个面板都有一些在此基础上设计的组件。我想在获得焦点时更改组件(JTextField)的背景颜色。 我有很多 TextField,我不想为所有组件编写 FocusListener。 有没有办法以聪明的方式做到这一点。
【问题讨论】:
您绝对应该按照@Robin 的建议考虑您的设计。通过工厂创建和配置应用程序的所有组件有助于使其对需求更改具有鲁棒性,因为只有一个位置可以更改,而不是分散在整个代码中。
此外,每个组件都有一个单独的侦听器,使控件靠近发生焦点引起的属性更改的位置,因此不需要在全局侦听器中进行状态处理。
也就是说,全局 focusListener 的技术(如:小心使用!)解决方案是向 KeyboardFocusManager 注册 propertyChangeListener。
一个快速的代码 sn-p(非常粗略的状态处理:-)
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);
【讨论】:
我不想为所有组件编写 FocusListener
所以你不想替换你的
JTextField textField = new JTextField();
由
JTextField textField = TextFieldFactory.createTextField();
其中TextFieldFactory#createTextField 是一种实用方法,可创建具有所需功能的JTextField。想详细说明一下吗?
【讨论】:
另一种方法是编写自己的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"));
}
}
}
【讨论】:
您可以将ProperyChangeListener 附加到KeyboardFocusManager @ 监控适当的更改
【讨论】: