Estoy tratando de crear algunos JTextFields más atractivos con una imagen y una pista. Para hacer esto hice un decorador que anula el método paintComponent. La razón por la que utilicé un decorador es porque quería aplicarlo a otros tipos de JTextField como JPasswordField.Decorar un JTextField con una imagen y sugerencia
Esto es lo que he hecho hasta ahora;
El problema, como se ve en la forma de la izquierda es que, a pesar de que he utilizado una JPasswordField la paintComponent parece ignorar lo que supongo que es el paintComponent contraseñas que presumiblemente hace los símbolos contraseña de enmascaramiento.
Así que la pregunta es, ¿cómo puedo evitar la duplicación del código para JTextFields y JPasswordFields, pero todavía tengo las diferentes funcionalidades como el enmascaramiento de contraseñas.
Este es el código del decorador;
public class JTextFieldHint extends JTextField implements FocusListener{
private JTextField jtf;
private Icon icon;
private String hint;
private Insets dummyInsets;
public JTextFieldHint(JTextField jtf, String icon, String hint){
this.jtf = jtf;
setIcon(createImageIcon("icons/"+icon+".png",icon));
this.hint = hint;
Border border = UIManager.getBorder("TextField.border");
JTextField dummy = new JTextField();
this.dummyInsets = border.getBorderInsets(dummy);
addFocusListener(this);
}
public void setIcon(Icon newIcon){
this.icon = newIcon;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int textX = 2;
if(this.icon!=null){
int iconWidth = icon.getIconWidth();
int iconHeight = icon.getIconHeight();
int x = dummyInsets.left + 5;
textX = x+iconWidth+2;
int y = (this.getHeight() - iconHeight)/2;
icon.paintIcon(this, g, x, y);
}
setMargin(new Insets(2, textX, 2, 2));
if (this.getText().equals("")) {
int width = this.getWidth();
int height = this.getHeight();
Font prev = g.getFont();
Font italic = prev.deriveFont(Font.ITALIC);
Color prevColor = g.getColor();
g.setFont(italic);
g.setColor(UIManager.getColor("textInactiveText"));
int h = g.getFontMetrics().getHeight();
int textBottom = (height - h)/2 + h - 4;
int x = this.getInsets().left;
Graphics2D g2d = (Graphics2D) g;
RenderingHints hints = g2d.getRenderingHints();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.drawString(hint, x, textBottom);
g2d.setRenderingHints(hints);
g.setFont(prev);
g.setColor(prevColor);
}
}
protected ImageIcon createImageIcon(String path, String description) {
java.net.URL imgURL = getClass().getResource(path);
if (imgURL != null) {
return new ImageIcon(imgURL, description);
} else {
System.err.println("Couldn't find file: " + path);
return null;
}
}
@Override
public void focusGained(FocusEvent arg0) {
this.repaint();
}
@Override
public void focusLost(FocusEvent arg0) {
this.repaint();
}
}
Y aquí es donde creo los campos;
JTextField usernameField = new JTextFieldHint(new JTextField(),"user_green","Username");
JTextField passwordField = new JTextFieldHint(new JPasswordField(),"bullet_key","Password");
Espero que no haya salido completamente en la dirección equivocada aquí!
Gracias!
EDITAR: De nuevo, cuanto más lo miro, es obvio que llamar a super.paintComponent (g) va a llamar al componente de pintura JTextFields, pero no veo cómo resolverlo sin duplicar el código.
¿Estáis destinados frontera Border = BorderFactory ...., solo 1 – mKorbel
Puede crear una CompoundBorder. Utilice el borde original como el borde exterior y luego utilice un MatteBorder con un icono como el borde interno – camickr
claro y directo, gracias – mKorbel