Java Swing:如何在监听器中修改JTextField子类文本及实现焦点逻辑
解决方案
1. 完善MyComponent类
先给自定义文本框加个存储默认文本的字段,后续恢复默认值时不用硬编码,更灵活:
import javax.swing.JTextField; import java.awt.Font; public class MyComponent extends JTextField { private int code; private String defaultText; // 保存初始的默认文本 public MyComponent(String text, int code) { super(text); this.defaultText = text; this.code = code; setFont(new Font("Calibri", Font.PLAIN, 30)); } public int getCode() { return code; } public String getDefaultText() { return defaultText; } }
2. 修改监听器类,同时处理点击和焦点事件
别用反射!JTextField本身就有setText()和getText()方法直接操作文本。另外,失去焦点不能靠mouseExited(鼠标移出文本框但没点其他地方,文本框还是有焦点的),得用FocusListener处理焦点丢失事件。让监听器同时实现MouseListener和FocusListener:
import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; public class MyListener implements MouseListener, FocusListener { public static final int ENTERNAME = 1; // 点击文本框时,如果是默认文本就清空 @Override public void mouseClicked(MouseEvent e) { MyComponent textField = (MyComponent) e.getSource(); if (textField.getCode() == ENTERNAME) { if (textField.getText().equals(textField.getDefaultText())) { textField.setText(""); } } } // MouseListener的其他空实现(接口要求必须实现所有方法) @Override public void mousePressed(MouseEvent e) {} @Override public void mouseReleased(MouseEvent e) {} @Override public void mouseEntered(MouseEvent e) {} @Override public void mouseExited(MouseEvent e) {} // 获取焦点时也清空默认文本(适配tab键切换焦点的场景) @Override public void focusGained(FocusEvent e) { MyComponent textField = (MyComponent) e.getSource(); if (textField.getCode() == ENTERNAME && textField.getText().equals(textField.getDefaultText())) { textField.setText(""); } } // 失去焦点时,如果文本为空就恢复默认文本 @Override public void focusLost(FocusEvent e) { MyComponent textField = (MyComponent) e.getSource(); if (textField.getCode() == ENTERNAME) { // 用trim()避免用户只输入空格的情况 if (textField.getText().trim().isEmpty()) { textField.setText(textField.getDefaultText()); } } } }
3. 主类中添加焦点监听器
原来只加了鼠标监听器,现在要把同一个监听器对象也添加为焦点监听器:
import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JLabel; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import java.awt.Insets; public class Main { public static void main(String[] args) { JFrame frame = new JFrame("My programm"); frame.setBounds(320, 80, 750, 600); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); MyComponent enterName = new MyComponent("Default name", MyListener.ENTERNAME); MyListener listener = new MyListener(); enterName.addMouseListener(listener); enterName.addFocusListener(listener); // 新增焦点监听器 JPanel panel = new JPanel(); JLabel labelName = new JLabel("Enter name: "); panel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.gridx = 0; panel.add(labelName, c); c.gridx = 1; c.insets = new Insets(0, 10, 0, 0); panel.add(enterName, c); frame.add(panel); frame.setVisible(true); } }
为什么不用反射?
JTextField已经封装了setText()、getText()这些操作文本的方法,直接调用就够了。反射操作私有字段不仅麻烦,还可能因为JDK版本变动导致代码失效,完全没必要。
内容的提问来源于stack exchange,提问作者Arina
相关产品推荐
相关产品推荐

