Capas con imagen de fondo en Java

Java es un lenguaje muy potente, pero hacer interfaces es algo que puede llegar a ser tan divertido como una patada en los cojones xD. El editor de Netbeans es muy potente, pero como usa un layout propio (auque puedes usar otros, los estandar de la API de Java) luego para exportarlo y empaquetarlo todo en un jar, debo de ser muy tonto que no se hacerlo, luego tenemos Eclipse, un IDE que es el puro desorden personificado, por mucho que intento ponerme con él, pierdo más tiempo mirando donde están las cosas que trabajando, es decir, toca hacerse las GUI’s a mano.
Una de las cosas que más he hecho y más veces he perdido el tiempo, es crear una capa/ventana/cuadrado/ComoQuierasLlamarlo con una imagen de fondo. Para hacer esta trivialidad, en Java tenemos que hacer la de dios para lograrlo, lo que viene a ser usar un JPanel y sobrecargar el método de pintado en el cual pintaremos toda la superficie con una textura creada de la imagen. Vamos que es una puta mierda. Este post me lo escribo para mi mismo :P, para que otras veces venga aquí y haga copy paste y deje de tener que estar siempre mirando código viejo. Let’s go!

Demo 1 – Ventanita simple con un fondo:

    Recursos:

  • -GUI.java: la “aplicación” verdadera
  • -images.java: Clase estática para crear texturas de una imagen
  • -fondo.png: Fondo, puede ser más pequeño que la ventana y de esa forma se repetirá. Acabo de hacer una imagén de 300x10px donde la mitad superior es negra y la mitad inferior es blanca. Adivinas el efecto que surgirá?, yeah, una cebra xD.

GUI.java

import java.awt.*;
import javax.swing.*;
import java.net.URL;
 
public class GUI extends JFrame
{
	private static GUI ventanaPrincipal; // Ventana principal
	private JPanel panel; // Capa sobre la que se trabajará
 
	private final URL imgFondo =  this.getClass().getResource("fondo.png");	
	private static TexturePaint fondo; // Textura con la que se pintará el fondo
 
	public static void main(String [] arg)
	{	// lanzamos aplicación
		javax.swing.SwingUtilities.invokeLater(new Runnable(){
			public void run()
			{
				lanzarAplicacion();
			}
		});
	}
	/**
	 * construye los objetos requeridos para el funcionamiento de la aplicacion
	 */
	private static void lanzarAplicacion()
	{
		// se crea la ventana
		ventanaPrincipal = new GUI("Demo guays");		
		// y la mostramos!
		ventanaPrincipal.setVisible(true);		
	}
 
	private GUI(String Titulo)
	{
		super(Titulo);
 
		panel = new JPanel()
		{
			private TexturePaint fondo = images.carga(imgFondo, this);
			protected void paintComponent(Graphics g)
			{
				super.paintComponent(g);
				Graphics2D g2d = (Graphics2D)g;
				Dimension d = getSize();
				g2d.setPaint(fondo);
				g2d.fill(new Rectangle(0,0,d.width,d.height));
			}
		};			
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setPreferredSize(new Dimension(300, 300));
		setSize(300,300);	
		getContentPane().add(panel);
	}
 
}

Images.java: Es un clase estática de la cual nos interesa el método carga(nombre_imagen, componente), el cual nos dará el tan preciado TexturePaint, la textura con la cual pintaremos felizmente. (nota: par de funciones no son mias, las saqué de un tutorial de java2d)

import java.awt.*;
import javax.swing.ImageIcon;
import java.awt.image.*;
import java.net.URL;
 
public class images
{
	private static TexturePaint cargaTextura(URL imageFile, Component c)
	{
		TexturePaint imageDev;
		try
		{
			Image img = (new ImageIcon(imageFile)).getImage();
			BufferedImage image = getBufferedImage(img , c);
			imageDev =  new TexturePaint(image, 
					new Rectangle(0, 0, image.getWidth(), image.getHeight())	
			);
		}catch(Exception e){
      	imageDev = null;
      	System.out.println(e.getMessage());	
      }
      return imageDev;
  }
 
	private static BufferedImage getBufferedImage(Image image, Component c)
	{
		waitForImage(image, c);
		BufferedImage bufferedImage = new BufferedImage(
			image.getWidth(c), image.getHeight(c), BufferedImage.TYPE_INT_RGB
		);
		Graphics2D g2d = bufferedImage.createGraphics();
		g2d.drawImage(image, 0, 0, c);
		return(bufferedImage);
	}
 
	private static boolean waitForImage(Image image, Component c)
	{
		MediaTracker tracker = new MediaTracker(c);
		tracker.addImage(image, 0);
		try{
			tracker.waitForAll();
		}catch(InterruptedException ie){}
		return(!tracker.isErrorAny());
	}
	/**
	 * Crea un textura de una imagen para un componente concreto
	 * @param s imagen a cargar
	 * @param c componente sobre el cual pintaremos
	 */
	public static TexturePaint carga(URL s, Component c)
	{
		TexturePaint image;
		image = cargaTextura(s, c);
		if (image == null)
			System.err.println("OMG! No puedo leer la imagen " + s);
		return image;
	}
}

Con esto obtenemos:

ventanajavapintada.jpg

Demo 2 – JPanelBackground: ya que estamos, hacemos un nuevo JPanel nuevo, no?

JPanelBackground

import javax.swing.JPanel;
import java.awt.*;
import java.net.URL;
 
public  class JPanelBackground extends JPanel
{
	private TexturePaint fondo;
 
	public JPanelBackground(URL imgFondo)
	{
		fondo = images.carga(imgFondo, this);
	}
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D)g;
		Dimension d = getSize();
		g2d.setPaint(fondo);
		g2d.fill(new Rectangle(0,0,d.width,d.height));
	}
}

Con esto GUI.java cambiará a ser más simple y limpio, concretamente los cambios serían:

(...)
public class GUI extends JFrame
{
	(...)
	private JPanelBackground panel; // Capa sobre la que se trabajará
	(...)
	private GUI(String Titulo)
	{
		super(Titulo);
 
		panel = new JPanelBackground(imgFondo);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		(...)
	}	
}

Todos los códigos fuentes están en este archivo 😉

Unos comentarios finales, todo esto nos permite, posteriormente, crear nuevos elementos sobre este JPanel que estarán por encima de la imagen que hemos pintado, si nos da igual esto (es decir, que no vamos a poner más cosas por encima), se podría hacer con un JLabel usando su método setIcon(new ImageIcon(“imagen.png”)), otra forma que muchos dirán sería usar un Canvas y su método setBackground, el cual es una ponzoña, pues al usarlo, el Canvas estará disparando eventos de repintado aparte de los usuales de su método Paint(), es decir, que con un Canvas habría que hacer lo que hemos hecho arriba con JPanel.

16 Thoughts on “Capas con imagen de fondo en Java

  1. Java es un lenguaje muy potente, pero hacer interfaces es algo que puede llegar a ser tan divertido como una patada en los cojones xD

    tan divertido como eso… y mucho más tambien… (alguien ha visto la peli de Hostel ? 😛 )
    De los IDEs, pues otro que es fantabuloso (fantastico y maravilloso al mismo tiempo) es el Kawa, que por momentos se volvía anti-intuitivo 😮

  2. Pero si este blog sólo lo leemos tus amiguitos y no nos enteramos de eso para que lo pones jeje.

  3. txus, kawa es solo para Windows, además no tiene editor de interfaces si no recuerdo mal.
    manolito, lo escribo para tenerlo aquí para mi, e igual a alguien más le sirve también 😛

  4. normandos on 19 August, 2006 at 22:30 said:

    hasta este post he llegado yo, que vivo en Uruguay porque necesitaba meter una imagen de fonde en un form del netbeans y hasta ahora no sabia como hacerlo…. meti unas key en google y me trajo hasta aqui…..cuando pruebe este codigo te digo si funciona o no, pero por ahora muchas gracias.
    Salu2
    Normandos

  5. Ing mario Medina on 21 September, 2006 at 17:36 said:

    Lo felicito su codigo es excelente sobre todo la elegancia de la segunda version donde mostro muy bien los patrones de diseño.

    me acaba de ayudar.

    si necesita codigos tutores de java escribame, se acaba de ganar un amigo. carmario55@gmail.com.

    algo mas yo estoy trabajando con un protocolo para captura de imagenes llamado twain si necesita algo. escribame

  6. Wílmer on 12 November, 2006 at 7:32 said:

    Wilmer says: Hola, estoy viendo algoritmos y lenguajes 2 en la Universidad y vamos por swing!!

    me sorprende la facilidad y la destreza con que programas… pues a mí ,al verdad, me causa un poco de dificultad…

    En el proyecto final… estoy quedado, además para que se vea bonito quiero poner una imagen de fondo, más no sé como, por eso encontré esta pagina, debo revisar el código, aunque sé que no es lo mismo una textura que una imagen!!!

    Si me puedes ayudar, desde colombia, te agradecería enormemente!!!!
    Gracias y te felicito

  7. Wilmer, es equivalente, en java para “pintar” necesitas una textura (fijate en el método cuando se hace g2d.setPaint(fondo); ahí estableces con qué vas a pintar), por lo tanto convertimos nuestra imagen de fondo en un TexturePaint y de esa forma ya podemos pintar toda la superficie del componente, lo que equivale a poner una imagen de fondo 🙂

  8. eynob on 15 January, 2007 at 23:59 said:

    Muchas gracias por este codigo es de gran ayuda, me estaba volviendo loco tratando de buscar algo hecho asi
    Desde Argentina, saludos y nuevamente gracias

  9. anonimo on 14 May, 2008 at 0:52 said:

    esta charrul esto mejor no publiquen nada!!!!!

  10. Ana on 9 July, 2008 at 13:06 said:

    Se puede hacer de otra forma mucho más sencilla:

    1) Se añade un LayeredPane.
    2) En él se añade un etiqueta (que pondremos sin texto y como icono la imagen que queremos mostrar), ajustando su tamaño al de la ventana.
    3) En el LayeredPane se añade otro panel (en la propiedad “Layer” ponemos “DRAG_LAYER”, para que quede sobre la imagen).
    4) En este otro panel ponemos todos los demás componentes de la ventana.

    (Todo esto lo he ehcho utilizando NetBeans 6.1)

  11. no tendras algo mas sencillo asi como para patitos 1 : ) n.n
    Simplemente quiero poner una imagen de fondo… y es algo urgente como para el miercoles : ) crees que se pueda si si si : )

    tc tq tc ta ptste
    ccc
    YOPI!!

  12. Glenn on 6 February, 2009 at 11:36 said:

    Muy buen ejemplo, cuesta encontrar código sencillo y al grano, gracias por éste aporte… justamente andaba buscando como hacer para poner no solamente una imagen sino dibujar sobre ella… en fin excelente!!

  13. Genial¡¡
    justo lo que estaba buscando¡¡
    lastima que no entendi ni verga del codigo… pero bueno hehe
    Si yo agarro un Jlabel, le doy icon y puedo meterle una imagen de fondo con el netbeans, pero dentro del Jlabel no puedo meter nada de elementos, en cambio si uso un JFrame o un JPanel ahi si puedo meter todos los elementos de la GUI pero en JFrame y JLabel no puedo poner un icon como imagen de fondo T_T
    alguien sabe como?

  14. Gracias por el código =)

  15. Yir on 21 May, 2010 at 2:49 said:

    Gracias!!

    Creí que no era posible.

  16. leon 41 on 31 October, 2010 at 2:00 said:

    como yo puedo hacer un background que cambien como este http://www.creed.com/#/music o como la de slipknot http://www.slipknot1.com/

Post Navigation