You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 12:30:58