如何在 JTextField 中显示淡灰色的“重影文本”?

Posted

技术标签:

【中文标题】如何在 JTextField 中显示淡灰色的“重影文本”?【英文标题】:How to display faint gray "ghost text" in a JTextField? 【发布时间】:2012-05-17 10:03:52 【问题描述】:

我不知道我是否得到了正确的名称,但我正在寻找是否有一种特定的方式来实现一个文本字段,以便当它没有焦点并且是空的时,一个微弱的灰色文本字符串显示在字段中。单击该字段时,文本应该消失,就像 *** 的搜索栏的工作方式一样。我知道我可以更改使用 setForeground() 并关注侦听器来完成此操作,但我只是想知道是否有人知道一些可以为我处理此问题的 Java 实现。

【问题讨论】:

AFAIK,没有。但我很乐意被告知否则 我可以告诉你,Swing 本身并不提供此功能(但有人可能已经编写了一个 3rd 方库来实现它)。 这可能会有所帮助:***.com/questions/1738966/… 使用来自 SwingX 的 JXTextField:swingx.java.net. @Elias,虽然我认为您的链接正是我正在寻找的,但该网站确实令人困惑......关于转移服务器的一些事情,它看起来只完成了一半,看不到尽头。虽然我确信下面的代码肯定会起作用,但我认为它对于我需要的东西来说有点过头了。我想我回到了我开始的地方:看起来我会自己做:P 【参考方案1】:

对于它的价值,我发现实际实现它很有趣,所以我想与你分享它(我不是在寻找投票)。

这真的是非侵入性的,因为您只需致电new GhostText(textField, "Please enter some text here...");。剩下的代码只是为了让它运行。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class Test 

    public static class GhostText implements FocusListener, DocumentListener, PropertyChangeListener 
        private final JTextField textfield;
        private boolean isEmpty;
        private Color ghostColor;
        private Color foregroundColor;
        private final String ghostText;

        protected GhostText(final JTextField textfield, String ghostText) 
            super();
            this.textfield = textfield;
            this.ghostText = ghostText;
            this.ghostColor = Color.LIGHT_GRAY;
            textfield.addFocusListener(this);
            registerListeners();
            updateState();
            if (!this.textfield.hasFocus()) 
                focusLost(null);
            
        

        public void delete() 
            unregisterListeners();
            textfield.removeFocusListener(this);
        

        private void registerListeners() 
            textfield.getDocument().addDocumentListener(this);
            textfield.addPropertyChangeListener("foreground", this);
        

        private void unregisterListeners() 
            textfield.getDocument().removeDocumentListener(this);
            textfield.removePropertyChangeListener("foreground", this);
        

        public Color getGhostColor() 
            return ghostColor;
        

        public void setGhostColor(Color ghostColor) 
            this.ghostColor = ghostColor;
        

        private void updateState() 
            isEmpty = textfield.getText().length() == 0;
            foregroundColor = textfield.getForeground();
        

        @Override
        public void focusGained(FocusEvent e) 
            if (isEmpty) 
                unregisterListeners();
                try 
                    textfield.setText("");
                    textfield.setForeground(foregroundColor);
                 finally 
                    registerListeners();
                
            

        

        @Override
        public void focusLost(FocusEvent e) 
            if (isEmpty) 
                unregisterListeners();
                try 
                    textfield.setText(ghostText);
                    textfield.setForeground(ghostColor);
                 finally 
                    registerListeners();
                
            
        

        @Override
        public void propertyChange(PropertyChangeEvent evt) 
            updateState();
        

        @Override
        public void changedUpdate(DocumentEvent e) 
            updateState();
        

        @Override
        public void insertUpdate(DocumentEvent e) 
            updateState();
        

        @Override
        public void removeUpdate(DocumentEvent e) 
            updateState();
        

    

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new Runnable() 
            @Override
            public void run() 
                init();
            
        );
    

    public static void init() 
        JFrame frame = new JFrame("Test ghost text");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel panel = new JPanel();
        JTextField textField = new JTextField();
        JButton button = new JButton("Grab focus");
        GhostText ghostText = new GhostText(textField, "Please enter some text here...");
        textField.setPreferredSize(new Dimension(300, 24));
        panel.add(textField);
        panel.add(button);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
        button.grabFocus();
    

【讨论】:

这可能有点挑剔,但您能否在不删除重影文本的情况下完成此操作,直到输入字符? Firefox 能够显示我在说什么:如果您打开一个新选项卡,地址栏会显示“搜索或输入地址”的幽灵文本,当您聚焦该字段时它不会消失,但会一直存在,直到您输入第一个字符。 这太棒了,但是截至 2018 年并使用 java 8,它是内置的吗?它真的应该是。 @ryan_m 我不知道,但事实并非如此,我不会感到惊讶。显然,Swing 将不再更新,只会被维护。【参考方案2】:

非常感谢纪尧姆,这非常好!

为了方便使用,我只是做了一些改动:

    使用 JTextComponent 而不是 JTextField,因此它适用于所有文本 输入 取出测试类并将其设为公开且非静态以使其独立

代码如下:

import java.awt.Color;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.JTextComponent;

public class GhostText implements FocusListener, DocumentListener, PropertyChangeListener

    private final JTextComponent textComp;
    private boolean isEmpty;
    private Color ghostColor;
    private Color foregroundColor;
    private final String ghostText;

    public GhostText(final JTextComponent textComp, String ghostText)
    
        super();
        this.textComp = textComp;
        this.ghostText = ghostText;
        this.ghostColor = Color.LIGHT_GRAY;
        textComp.addFocusListener(this);
        registerListeners();
        updateState();
        if (!this.textComp.hasFocus())
        
            focusLost(null);
        
    

    public void delete()
    
        unregisterListeners();
        textComp.removeFocusListener(this);
    

    private void registerListeners()
    
        textComp.getDocument().addDocumentListener(this);
        textComp.addPropertyChangeListener("foreground", this);
    

    private void unregisterListeners()
    
        textComp.getDocument().removeDocumentListener(this);
        textComp.removePropertyChangeListener("foreground", this);
    

    public Color getGhostColor()
    
        return ghostColor;
    

    public void setGhostColor(Color ghostColor)
    
        this.ghostColor = ghostColor;
    

    private void updateState()
    
        isEmpty = textComp.getText().length() == 0;
        foregroundColor = textComp.getForeground();
    

    @Override
    public void focusGained(FocusEvent e)
    
        if (isEmpty)
        
            unregisterListeners();
            try
            
                textComp.setText("");
                textComp.setForeground(foregroundColor);
            
            finally
            
                registerListeners();
            
        

    

    @Override
    public void focusLost(FocusEvent e)
    
        if (isEmpty)
        
            unregisterListeners();
            try
            
                textComp.setText(ghostText);
                textComp.setForeground(ghostColor);
            
            finally
            
                registerListeners();
            
        
    

    @Override
    public void propertyChange(PropertyChangeEvent evt)
    
        updateState();
    

    @Override
    public void changedUpdate(DocumentEvent e)
    
        updateState();
    

    @Override
    public void insertUpdate(DocumentEvent e)
    
        updateState();
    

    @Override
    public void removeUpdate(DocumentEvent e)
    
        updateState();
    


【讨论】:

如何以编程方式检查空的 jTextField? getText 方法返回 GhostText :| 很好,如果在 focusLost 中添加以下内容会更好:else unregisterListeners();尝试 textComp.setForeground(foregroundColor); 最后 registerListeners();

以上是关于如何在 JTextField 中显示淡灰色的“重影文本”?的主要内容,如果未能解决你的问题,请参考以下文章

保持 jButton 灰色直到 jTextFields != null

在C语言中,如何改变程序运行时显示屏的颜色?

如何设置计时器以向 JTextField 显示结果时间?

如何只允许在 jTextField 中引入数字?

不要为可拖动元素显示重影

如何在 JLabel 和 JTextField 上显示非科学格式的值?