Viel schöner ist es, wenn das Dokument davon unberührt bliebe. Das Dokument als Model der Textkomponente ist ja eigentlich leer, auch wenn der Hinweis in der Komponente angezeigt wird. Ganz ohne Listener kommt diese Klasse daher und zeichnet den Hinweis in einem Highlighter.
[Highlight=Java]/* (@)JHintingTextField.java */
/* Copyright 2009 Sebastian Haufe
* Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */
package com.ebenius.widget;
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.Highlighter.HighlightPainter;
/**
* An enhanced text field, showing an {@link #getEmptyTextHint() empty text}
* hint on its view, if the {@link #getText() text content} is empty.
*
* @version $Revision: 1.1 $ as of $Date: 2009/04/08 19:13:04 $
* @author Sebastian Haufe
*/
public class JHintingTextField extends JTextField {
/** Serial version UID */
private static final long serialVersionUID = 5061790840224877676L;
// -------------------------------------------------------------------------
// Constructors
// -------------------------------------------------------------------------
/**
* Creates a new <code>JHintingTextField</code>.
*/
public JHintingTextField() {
installHighlightPainter();
}
/**
* Creates a new <code>JHintingTextField</code>.
*
* @param columns the number of preferred columns to calculate preferred
* width
*/
public JHintingTextField(int columns) {
super(columns);
installHighlightPainter();
}
/**
* Creates a new <code>JHintingTextField</code>.
*
* @param text the text to show in the text field
*/
public JHintingTextField(String text) {
super(text);
installHighlightPainter();
}
/**
* Creates a new <code>JHintingTextField</code>.
*
* @param text the text to show in the text field
* @param columns the number of preferred columns to calculate preferred
* width
*/
public JHintingTextField(String text, int columns) {
super(text, columns);
installHighlightPainter();
}
/**
* Creates a new <code>JHintingTextField</code>.
*
* @param doc the text model
* @param text the text to show in the text field
* @param columns the number of preferred columns to calculate preferred
* width
*/
public JHintingTextField(Document doc, String text, int columns) {
super(doc, text, columns);
installHighlightPainter();
}
// -------------------------------------------------------------------------
// Hinting highlighter code
// -------------------------------------------------------------------------
private void installHighlightPainter() {
Highlighter highlighter = getHighlighter();
System.out.println(highlighter);
try {
highlighter.addHighlight(0, 0, createHighlightPainter());
} catch (BadLocationException ex) {
assert false : "0:0 illegal?"; //$NON-NLS-1$
}
}
protected HighlightPainter createHighlightPainter() {
return new Highlighter.HighlightPainter() {
final JLabel label = new JLabel("", //$NON-NLS-1$
SwingConstants.TRAILING);
final int gap = 3;
public void paint(
Graphics g,
int p0,
int p1,
Shape bounds,
JTextComponent c) {
final String hint = (String) c.getClientProperty( //
"emptyTextHint"); //$NON-NLS-1$
if (hint == null
|| hint.length() == 0
|| c.getDocument().getLength() != 0) {
return;
}
label.setText(hint);
final Insets ins = c.getInsets();
final boolean ltr = c.getComponentOrientation().isLeftToRight();
if (ltr) {
ins.right += gap;
} else {
ins.left += gap;
}
final Dimension pref = label.getPreferredSize();
final int prHeight = pref.height;
final int prWidth = pref.width;
final int w = Math.min(c.getWidth() - ins.left - ins.right, prWidth);
final int h = Math.min(c.getWidth() - ins.top - ins.bottom, prHeight);
final int x = ltr ? c.getWidth() - ins.right - w : ins.left;
final int parentHeight = c.getHeight() - ins.top - ins.bottom;
final int y = ins.top + (parentHeight - h) / 2;
label.setForeground(Color.GRAY);
label.setOpaque(false);
SwingUtilities.paintComponent(g, label, c, x, y, w, h);
}
};
}
// -------------------------------------------------------------------------
// Bean getters and setters
// -------------------------------------------------------------------------
/**
* Returns the emptyTextHint.
*
* @return the emptyTextHint
*/
public String getEmptyTextHint() {
return (String) getClientProperty("emptyTextHint"); //$NON-NLS-1$
}
/**
* Sets the emptyTextHint.
*
* @param hint the emptyTextHint to set
*/
public void setEmptyTextHint(String hint) {
putClientProperty("emptyTextHint", hint); //$NON-NLS-1$
repaint();
}
}[/Highlight]
Zu testen mit diesem Code: [Highlight=Java]public static void main(String[] args) {
final JPanel contentPane = new JPanel(new BorderLayout(6, 6));
final JHintingTextField comp = new JHintingTextField(20);
comp.putClientProperty("emptyTextHint", "Name, Vorname");
contentPane.add(comp);
contentPane.add(new JButton("Dummy"), BorderLayout.LINE_END);
final JFrame f = new JFrame("Test Frame: JHintingTextField");
f.setContentPane(contentPane);
f.pack();
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
}[/Highlight]
Ebenius