agosto 15, 2006


Java : Personalizando componentes



A veces uno quisiera personalizar componentes en JAVA esto es super sencillo, por ejemplo si quisiera un JTextField como los de Deskbar que tiene algo como una lupa en el textfield.

Qué haremos ?:
Un JTextField que tenga incluido una imagen.

Jtextfield con icono de busqueda
Jtextfield que haremos.


Manos a la obra :

icono de la lupa del ejemplo
El icono que utilizaremos en el ejemplo.

*Para empezar crearemos una clase que extienda de JTextField, que sera la clase que personalizaremos.

*Luego declaramos la imagen que se dibujara, en el ejemplo se llama "stock_zoom.png"

//la imagen que incorporare al componente
String urlImage = getClass().getResource("stock_zoom.png");

private Image image = new ImageIcon( urlImage ).getImage();


*Para agregar la imagen del JtextField lo que modificaremos sera la forma de pintarse del componente. o sea tendremos que Sobrescribir el método paint
para que además de dibujar el componente por defecto dibuje una imagen.

//sobrescribiendo el componente
@Override
public void paint(Graphics g)
{
if ( isVisible() )
{
super.paint(g);//llamando al dibujado por defecto

g.drawImage( image, 0, 0, null); // dibujo la imagen
}
}

*En el código se ve como después de dibujar el componente por defecto, dibuja
una imagen.
Hasta ahora ya esta listo se ve como teniamos pensado al comienzo, salvo que la posición del cursor es tapada por la imagen. asi que nos falta setear el Margen del componente al tamaño de la imagen al momento de construir el objeto.

//agrego un margen en los constructores
{
getMargin().left = image.getWidth(null);
}

y listo eso seria las partes importantes del codigo y si tienes sugerencias ideas dudas, o quieren mejorar el JTextField con esquinas curvadas ..etc.. dejen el comentario
Y ahora el codigo completo...



Imagen que debe estar en el mismo directorio de la clase :


codigo:

import java.awt.Graphics;
import java.awt.Image;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
import javax.swing.text.Document;


/**
* @author flavin
* @date 15-08-2006
* @version $Id$
*/
public class BotonBusqueda extends JTextField{

//la imagen que incorporare al componente
private Image image =
new ImageIcon( getClass().getResource("stock_zoom.png") )
.getImage();

{//agrego un margen constructores
getMargin().left = image.getWidth(null);
}

//agrego los constructores del jtextfield
public BotonBusqueda() {
super();
}

public BotonBusqueda(Document doc,String text,int columns) {
super(doc, text, columns);
}

public BotonBusqueda(int columns) {
super(columns);
}

public BotonBusqueda(String text, int columns) {
super(text, columns);
}

public BotonBusqueda(String text) {
super(text);
}

@Override
public void paint(Graphics g)
{
if ( isVisible() ) { //sobrescribiendo el componente
super.paint(g);
g.drawImage( image, 0, 0, null); // dibujo la imagen
}
}

public static void main(String[] args) {
JFrame jframe = new JFrame();
jframe.setDefaultCloseOperation(
WindowConstants.EXIT_ON_CLOSE );

jframe.add( new BotonBusqueda() );

jframe.pack();
jframe.setVisible( true );
}

}


13 comentarios:

  1. Siempre dando buenas ideas, gracias!

    Una sugerencia a lo que pusiste, sería bueno siempre agregar una leve separación entre el jtextfield y la imagen, en vez de ponerla en el 0,0 mejor en el 2,2 o algo que se vea bien. También dejar un margen entre el cursor y la imagen, así el margen derecho sería el ancho de la imagen + los pixeles de separacion + pixeles entre el cursor y la imagen :P

    Acá una pidiendo que se hable acerca de los bordes redondeados o lo que se te ocurra para mejorarlo :D

    Abrazos!

    ResponderEliminar
  2. Tienes toda la razon, se ve mejor :-)
    Lo otro bueno y que también se ve mejor es tener las esquinas redondeadas en vez de las rectas que tiene por defecto.. ( al estilo de las de mac.)

    ResponderEliminar
  3. Oye por que mearca un error en el @Override?

    Me marca este error
    illegal character: \64
    @Override

    ResponderEliminar
  4. @override es una anotation que funcionan desde java 1.5 si quieres lo puedes sacar no hay problemas

    http://es.wikipedia.org/wiki/Anotaci%C3%B3n_Java

    ResponderEliminar
  5. se puede convertir un componente swing a 3D

    ResponderEliminar
  6. Hola, muy interesante.
    Tengo una duda, sabrás cómo puedo agregar un Jtextfield a un jframe que esta dibujando imágenes?, es que al agregarlo es tapado por la imagen de fondo.

    ResponderEliminar
  7. Hola tú problema son los Layouts, debes escoger un layout(GridLayout, BorderLayout... etc) que se acomode a lo que tienes en mente y luego agregar la imagen y el jtextfield en el contenedor.

    Prueba algo como

    import java.awt.*;
    import java.applet.Applet;
    public class ButtonGrid extends Applet {
    public void init() {
    ImageIcon icon = new ImageIcon("images/middle.gif");

    setLayout(new GridLayout(3,2));
    add(new Jtextfield("1"));
    add(new JLabel(icon));
    }
    }

    ResponderEliminar
  8. muchas gracias, aunque no se si esto solo funcione con los Applets por que yo estoy usando JFrame, deja checo, ojalá que se arregle.

    ResponderEliminar
  9. es lo mismo no te preocupes te recomiendo que leas esto

    http://java.sun.com/docs/books/tutorial/uiswing/layout/using.html

    ResponderEliminar
  10. no era los layout, lo arreglé de otra forma, pero ahora el problema es que para que la imagen se vea tengo que darle maximizar y ya dibuja el fondo y los componentes...

    ResponderEliminar
  11. Hola gracias por el aporte, me gustaría ver si me puedes ayudar estoy tratando de personalizar un jtextfield validando la entrada para que solo permita el ingreso de numeros ademas le he agregado un jlabel a la par para que en caso de que el usuario ingrese una legra el jlabel aparezca y diga "Solo números".
    Bueno mi problema es que a la hora de utilizar el siguiente método jtextsolonumeros.getText();
    me dice que el metodo .getText() no esta definido en mi control personalizado entonces me pregunta de que si quiero crearlo. Pero yo tengo entendido que si estoy creando un control personalizado podria heredar todo desde la clase jtextfield.
    Me gustaria que me ayudaras.

    ResponderEliminar
  12. Maldita sea sin van a ayudar ayuden bien

    ResponderEliminar