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

如何为登录窗口的JTextField添加获焦消失的灰色提示文本?

优雅实现带占位符的登录输入框

当然可以实现!而且完全不用你提到的那种focusGained/focusLost事件的繁琐方式——我们有更简洁优雅的解决方案:通过自定义JTextField子类,重写它的paintComponent方法来绘制灰色占位符文本,所有逻辑内聚在组件内部,符合Swing的渲染机制。

自定义带占位符的TextField组件

首先创建一个继承自JTextField的自定义类,专门处理占位符的渲染:

package com.soci.example;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JTextField;

public class PlaceholderTextField extends JTextField {
    private String placeholder;

    public PlaceholderTextField(String placeholder) {
        this.placeholder = placeholder;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 仅当文本为空且组件未获得焦点时,绘制灰色占位符
        if (getText().isEmpty() && !hasFocus()) {
            g.setColor(Color.GRAY);
            // 对齐方式和输入文本保持一致,确保视觉统一
            g.drawString(placeholder, getInsets().left, g.getFontMetrics().getMaxAscent() + getInsets().top);
        }
    }

    // 提供修改占位符的方法
    public void setPlaceholder(String placeholder) {
        this.placeholder = placeholder;
        repaint();
    }

    public String getPlaceholder() {
        return placeholder;
    }
}

在登录窗口中使用该组件

接下来就可以在你的登录窗口里直接使用这个自定义组件,设置对应的占位符提示:

package com.soci.example;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.GridLayout;
import java.awt.Dimension;

public class LoginFrame extends JFrame {
    public LoginFrame() {
        setTitle("登录窗口");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(300, 150));
        
        JPanel panel = new JPanel(new GridLayout(2, 1, 5, 5));
        panel.setBorder(javax.swing.BorderFactory.createEmptyBorder(20, 20, 20, 20));
        
        // 用户名输入框,提示"请输入用户名"
        PlaceholderTextField usernameField = new PlaceholderTextField("请输入用户名");
        panel.add(usernameField);
        
        // 密码输入框,提示"请输入密码"
        PlaceholderTextField passwordField = new PlaceholderTextField("请输入密码");
        panel.add(passwordField);
        
        add(panel);
        pack();
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        // 在Swing事件线程中启动窗口
        javax.swing.SwingUtilities.invokeLater(() -> {
            new LoginFrame().setVisible(true);
        });
    }
}

针对密码框的优化(可选)

如果你的密码输入需要隐藏字符,建议改用JPasswordField,同样可以用类似的方式自定义:

package com.soci.example;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPasswordField;

public class PlaceholderPasswordField extends JPasswordField {
    private String placeholder;

    public PlaceholderPasswordField(String placeholder) {
        this.placeholder = placeholder;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        // 判断密码是否为空(避免使用过时的getText()方法)
        if (getPassword().length == 0 && !hasFocus()) {
            g.setColor(Color.GRAY);
            g.drawString(placeholder, getInsets().left, g.getFontMetrics().getMaxAscent() + getInsets().top);
        }
    }

    public void setPlaceholder(String placeholder) {
        this.placeholder = placeholder;
        repaint();
    }

    public String getPlaceholder() {
        return placeholder;
    }
}

方案优势

  • 完全不需要监听焦点事件,逻辑内聚在组件内部,代码更简洁
  • 占位符的渲染遵循Swing的绘制流程,视觉效果更稳定
  • 自定义组件可复用,其他需要占位符的场景直接调用即可

内容的提问来源于stack exchange,提问作者Tobias Goetz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:22:37