Вопрос по java, swing – Как отобразить слабый серый «текст-призрак» в JTextField?

18

Я не знаю, получил ли я правильное имя для него, но я смотрю, есть ли конкретный способ реализации текстового поля, чтобы, хотя оно не имело фокусировки и было пустым, слабая серая строка текст отображается в поле. При щелчке по полю текст должен исчезнуть, точно так же, как работает панель поиска, такая как в StackOverflow. Я знаю, что я могу изменить использованиеsetForeground() и сосредоточить внимание слушателей на этом, но мне просто интересно, знает ли кто-нибудь какую-нибудь реализацию Java, которая могла бы справиться с этим для меня.

Это может помочь: / Stackoverflow.com вопросы / 1738966 / ... Ranga
AFAIK, нет. Но я был бы рад, если бы мне сказали инач Guillaume Polet
Используйте JXTextField от SwingX: Swingx.java.net. elias
Я могу сказать, что Swing не предоставляет этого изначально (но кто-то, возможно, написал стороннюю библиотеку для этого). Greg Kopff
@ Элиас, хотя я думаю, что твоя ссылка - это именно то, что я ищу, сайт действительно сбивал с толку ... Что-то о переносе серверов, и он выглядел только наполовину законченным, а конца не видно. И хотя я уверен, что приведенный ниже код, безусловно, будет работать, я думаю, что это немного за то, что мне нужно. Я думаю, что я вернулся к тому, с чего начал: похоже, я просто сделаю это сам: P Z1MM32M4N

Ваш Ответ

2   ответа
40

мне было интересно на самом деле реализовать его, поэтому я решил поделиться им с вами (я не ищу голоса).

Это действительно неинвазивно, так как все, что тебе нужно сделать, это позвонить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();
    }
}
"Я не ищу голоса" Круто. +1 Смирись. ;) Andrew Thompson
Это может быть немного придирчиво, но вы могли бы сделать это, не удаляя призрачный текст, пока символ не будет напечатан? Firefox может показать то, о чем я говорю: если вы откроете новую вкладку, в адресной строке появится текст с надписью «Поиск или введите адрес», который не исчезнет при фокусировке поля, но останется до тех пор, пока вы не введете первый символ. ryvantage
@ ryan_m Я понятия не имею, но я не удивлюсь, что это не так. Судя по всему, Swing больше не будет обновляться и будет только поддерживаться. Guillaume Polet
это круто, но с 2018 года и с использованием Java 8 это уже встроено? это действительно должно быть. ryan_m
8

Я просто изменил несколько вещей для простоты использования:

used 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: | do01
Nice, и еще лучше, если в focusLost вы добавите это: else {unregisterListeners (); try {textComp.setForeground (foregroundColor); } finally {registerListeners (); }} Pierre-Arthur Ferraro

Похожие вопросы