miércoles, 8 de agosto de 2012

Poner Imagen de fondo en un JPanel

Buenas amigos, en este nuevo tema veremos como poner una imagen de fondo a un JPanel desde una imagen situada en el interior de nuestro proyecto. Para ello primero debemos crear una carpeta dentro de la carpeta "src" del proyecto:




    • Pinchamos con el botón derecho del ratón encima de la carpeta "src" del proyecto, en el menú que se despliega pincháis en "Nuevo" y posteriormente elegís "carpeta", le ponéis el nombre que deseéis, yo para este tema le pondré de nombre "imágenes"



    • Ya tenemos nuestra carpeta creada, ahora debemos agregarle una imagen, para ello pinchamos  sobre la carpeta creada (os tiene que salir con un símbolo parecido al de paquete, pero en color blanco) y le dais a la opción de "importar"



    • Se nos abrirá una ventana con muchas carpetas, en este momento solo nos interesa la carpeta "General", pincháis en ella y se os desplegará otro menú donde debéis elegir la opción de "Sistema de archivos"

    • Se os abrirá una ventana donde deberéis elegir el directorio donde está la imagen, que os aparecerá en el cuadrado izquierdo, y en el derecho os saldrá todos los archivos que tenéis en ese directorio, solamente elegís vuestra imagen y le dais a "Finalizar". Fijaos antes de darle a "Finalizar" que la carpeta de destino sea la del proyecto.

    • Bien, ya tenemos una imagen dentro de nuestro proyecto java

Ya hemos visto como introducir una imagen en un proyecto Java, ahora veremos como podemos hacer que luzca en nuestro proyecto. Para ello vamos a realizar 2 clases:
  1. Una clase que herede de la clase JPanel para poder modificarla a nuestro gusto.
  2. Una clase que herede de la clase JFrame y donde nuestra imagen será mostrada.
Primera Clase:

    • Creamos una nueva clase, yo la he llamado Panel, que hereda de la clase JPanel.
    • Creamos dos atributos, ImageIcon y String. 
        • ImageIcon cargará la imagen en una variable llamada "imagen".
        • String pasará la URL a ImageIcon. La String es llamada "nombre", pero eso a sido porque no me he dado cuenta de lo que hacía...estaba un poco en la inopia, podéis llamarla url si os es más fácil.
    • Creamos un constructor con un parámetro (String nombre) y le decimos a la clase que ese parámetro que va a ser igual al parámetro que tenemos en la clase:
        • this.nombre=nombre;
    • Posteriormente invocamos el método "paint" para que nos ayude a pintar la imagen.
    • Dentro de este método creamos un objeto de la clase "Dimension" que obtiene el tamaño del Panel en todo momento(OJO, Java no pilla la letra "ñ").
        • Dimension tamanio=getSize();
    • Creamos un objeto de la clase ImageIcon y le indicamos donde tiene que buscar el archivo, en este caso es dentro del proyecto, para ello utilizamos el siguiente código:
        • imagen=new ImageIcon(getClass().getResource(nombre));
        • Donde "nombre" será la URL que le pasemos por el constructor.
    • Ahora le decimos a la Clase Graphics que nos pinte la imagen según los parámetros que le pasemos
    • Indicamos que el panel será transparente (ya que si no, no se vería la imagen)
    • Y finalmente le decimos a "super"que lo pinte.
        • super.paint(g);
Bien, esta sería la primera clase que deberíamos tener, ahora bien, esta clase por si sola no muestra nada, ni siquiera tiene un MAIN, debemos crear otra para mostrar nuestra imagen en una ventana.

Segunda Clase:


    • Creamos una clase que herede de JFrame.
    • En la MAIN creamos un objeto de esta misma clase:
        • Fondo f=new Fondo();
    • Le damos un tamaño:
        • f.setSize(400,300);
    • Lo hacemos visible:
        • f.setVisible(true);
    • Creamos un objeto de la clase que hicimos anteriormente, en mi caso se llamaba "Panel", y le pasamos la url de nuestra imagen:
        • panel p=new Panel("/imagenes/fondo.jpg")
    • Es muy importante que empiece con una barra, así le indicamos que está dentro de "src", y es muy importante también que indiquemos el nombre del archivo.
    • Finalmente añadimos el objeto de Panel a la Frame:
        • f.add(p);
    • Y ya está, si hemos seguido bien todos los pasos os deberá de quedar una bonita ventana con una imagen de fondo

Eso es todo, espero a ver ayudado a alguien. Un saludo a todos.

30 comentarios:

  1. hola me gusta que expliques cosas q para algunos nos resulte dificil.. podrias explicar como hacer que esa imagen sea transparente para que le pongamos botones encima y la foto no llame tanto la atencion?? gracias..

    ResponderEliminar
    Respuestas
    1. Buenas Pablo, respecto a la pregunta que me haces, siento decirte que no, no conozco ninguna forma en java de hacer lo que dices, ahora bien, no significa que no exista, me explico.

      Cuando creamos la clase Panel que hereda de JPanel, le indicamos en el método Graphics que el panel va a ser "transparente" para que podamos observar lo que va a ir detrás de él. Si vas al código y cambias "setOpaque(false)" por "setOpaque(true)" comprenderás lo que te digo. Ahora bien, lo que tu deseas es tener grados de transparencia para que la imagen se vaya difuminando. El problema es que la imagen que le ponemos esta ya definida, es decir, la elegimos nosotros. Entonces la solución que yo le veo son 2 posibles, una bastante fácil y otra más complicada.

      La primera es que tu mismo, antes de insertar la imagen la edites con algún editor tipo photoshop, photoscape, paint...o el que mejor manejes, y tu mismo le apliques transparencia, bajadas de brillo, etc, a la imagen.

      La segunda sería utilizando la clase File (que será la siguiente que explique y es la que maneja archivos), y a partir de ahí encontrar alguna forma de difuminar esa imagen, aunque es complicado, ya lo digo, pero no imposible.

      Lo mejor que puedes hacer es la primera opción, ya que simplifica muchas cosas, código, comederos de cabeza, tiempo, etc...

      Siento no poder ayudarte un poco más, pero esto es lo que hace los desarrolladores, se van a su diseñador gráfico y le dicen, "quiero una imagen así, así y así" y la agregan.

      Un saludo y espero haberte ayudado aunque solo sea un poco.

      Eliminar
    2. Buenas Pablo, he estado investigando un poco por la red y he visto que utilizando el paquete Graphics2D es posible crear un panel translucido muy fácilmente, aquí te dejo el sitio:
      http://edisoncor.wordpress.com/2007/11/26/crear-un-panel-transparente/

      Aún así, no se si la imagen quedará como pides. Para los próximos días agregaré un mini apartado en este tema para poner un panel translucido.

      Un saludo

      Eliminar
  2. Me parece interesante tu codigo porque con una sola clase jpanel podemos poner fondo a muchos jframe y con distintas imagenes.
    He implementado el codigo y le he agregado esta linea en el Main f.setExtendedState(MAXIMIZED_BOTH); para que el jframe inicie maximizado
    Lo que quiero es que pueda cambiar el tamaño del jframe y la imagen se ajuste al jframe cuando lo maximizo o restauro el tamaño,,osea que la imagen se acople al tamaño del jframe y siempre se muestre la imagen en su totalidad

    ResponderEliminar
    Respuestas
    1. Hola muy buenas. Me alegra que te guste, de esta forma conseguirás lo que pides, que la imagen se adapte, gracias a la clase "Dimension" y a su método getSize(), el cual devuelve un objeto de tipo "Dimension", que hace que nuestra imagen se adapte todo el tiempo al tamaño de la frame. ^^

      Un saludo.

      Eliminar
  3. Hola, estoy haciendo un proyecto y quiero meter una imagen como fondo, he creado la primera clase como dices y en el main de la clase que ejecuta la venta principal del programa he introducido lo de la segunda clase, pero ejecuto y nada, me aparece todo lo que tenia antes pero sin la imagen de fondo.

    Esta es la clase1:

    package presentacion;

    import java.awt.Dimension;
    import java.awt.Graphics;
    import javax.swing.ImageIcon;
    import javax.swing.JPanel;

    public class imagenFondo extends JPanel
    {

    ImageIcon imagen;
    String url;

    public imagenFondo(String url)
    {
    this.url=url;
    }

    public void paint(Graphics g)
    {
    Dimension tamanio= getSize();
    imagen = new ImageIcon(getClass().getResource(url));
    g.drawImage(imagen.getImage(), 0, 0, tamanio.width, tamanio.height, null);
    setOpaque(false);
    super.paint(g);
    }
    }

    ResponderEliminar
  4. y aqui el main de la clase2:

    public static void main(String[] args)
    {
    Visor visor1=new Visor();
    visor1.setSize(600,450);
    visor1.setVisible(true);
    imagenFondo img = new imagenFondo("/Users/jon/Desktop/segundo trimestre/prog2/eclipse/MyWeather/src/imagenes/fondo.jpg");
    visor1.add(img);
    }

    ResponderEliminar
    Respuestas
    1. Buenas Jon, cuando le pasas la ruta por constructor, se la pasas mal, intenta esto:

      imagenFondo img = new imagenFondo("/imagenes/fondo.jpg");

      La clase 1 utilizas la expresión "getClass().getResource(url)", eso significa que te va a buscar en carpetas dentro de tu proyecto, al pasarle la ruta que le has pasado empieza a buscar en el directorio del proyecto la carpeta "Users", al no encontrarla, peta.

      Suerte y prueba como te he dicho, veras como funciona.

      Un saludo.

      Eliminar
  5. Hola , muchas gracias por tu tutorial me ha servido bastante y me ha salido, queria saber si sabes como podria en lugar de utilizar una clase normal para llamar al panel, llamarlo desde un jframe , es decir lo que pasa es que necesito agregarle botones al jframe y lo quisiera hacer de forma grafica y no por medio de codigo, de antemano muchas gracias

    ResponderEliminar
    Respuestas
    1. Buenas Mike, en este ejemplo lo hago todo manual, con lo que no te va a salir la vista diseño. Para que te aparezca, yo utilizo WindowBuilder. Para acceder a él, te vas a la pestaña "Nuevo/Otros" donde se te abrirá una ventana con carpetas, busca una que ponga "windowBuilder" le pinchas y se te abrira un submenu donde tienes un conjunto de ventanas y dialogos, eliges "JFrame" y en ese momento eclipse te prepara una clase que herede de JFrame con la cual ya podrás acceder a la vista de diseño y jugar con ella, pudiendo ir alternando entre diseño y código. Par abrir la vista diseño o la vista código, tienes, en la ventana (en eclipse) de tu clase, abajo a la izquierda dos pestañas una que pone "source o código" y otra que pone "Design o Diseño", segun lo tengas en ingles o español.

      Bien, el resto del tuto es igual, es decir, para poner una imagen de fondo en un JPanel debes de seguir creando la clase que herede de JPanel y luego invocarla en la clase JFrame, pero ya te digo que eso es igual, las únicas diferencias es que ahora en la JFrame creamos los elementos en el constructor en vez de como yo lo tengo en este ejemplo, en la main, y que ahora podemos acceder a la vista diseño pudiendo poner todos los botones que queramos y como queramos.

      No se si he contestado tu duda.

      Un saludo

      Eliminar
  6. Hola:
    ¿Y si en lugar de tenerla en 'src' la ponemos en otra 'Source Folder' del proyecto? ¿Cómo pasamos la ruta en ese caso?
    Gracias.
    Terron

    ResponderEliminar
  7. hola, me ayudo mucho tu código, pero tengo una duda, como le puedo insertar botones, combos, etiquetas, etc, con el fondo??

    ResponderEliminar
    Respuestas
    1. Tienes que agregarlo al objeto panel de la clase Fondo, por ejemplo, para añadir un JComboBox sería:

      jComboBox jcb=new JComboBox();//Tenemos creado nuestro Combo

      Panel p=new Panel("/imagenes/fondo.jpg");//Creamos nuestro Panel con imagen de fondo
      p.add(jcb);//Agregamos a nuestro Panel el combo

      Posteriormente agregamos nuestro Panel a la clase que hereda de Frame:

      f.add(p);

      Y así sucesivamente con lo que quieras ir agregando.

      Un saludo

      Eliminar
  8. muy importante e interesante tu código, sobretodo para los que estamos empezando con interfaz gráfica en java. agradecido con usted Bartolome

    ResponderEliminar
  9. me pareció muy importante tu código le estoy continuando ya le agregue un JButton pero no ce como darle la acción al botón
    que al momento de picarle me salga un jOption

    ResponderEliminar
  10. me pareció muy importante tu código le estoy continuando ya le agregue un JButton pero no ce como darle la acción al botón
    que al momento de picarle me salga un jOption

    ResponderEliminar
    Respuestas
    1. Un ejemplo de eso que dices sería asi;

      JButton btnEntrar = new JButton("Entrar");
      btnEntrar .addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
      //aqui dentro le dices a que panel, frame, ... quieres que te dirija cuando hagas click en el botón Entrar
      }
      });

      desde actionPerdormed además puedes hacer que se ejecute un método o todo lo que quieras

      Eliminar
  11. espero y me puedas ayudar gracias cuento con su colaboracion bartolome

    ResponderEliminar
  12. Haber si alguien me puede ayudar porque me estoy volviendo loca.
    He creado un ejecutable que tiene bastantes jpanel y jframe y toda la pesca, pero cuando genero el .jar de mi archivo no me muestra las imagenes que tengo añadidas en el jpanel principal de mi programa, he probado con rutas para las imagenes dentor de mi programa, fuera y nada no me las muestra.
    A alguien le ha pasado esto y sabe que puedo hacer.
    Gracias de ante mano :P

    ResponderEliminar
  13. El codigo esta excelente solo quisiera Saber si le asigno a JPanel un LayoutManager y se lo paso en el constructor como lo puedo asignar

    ResponderEliminar
  14. Excelente lo que, buscaba las otras paginas pura basura ofrecian

    ResponderEliminar
  15. me da error al moemento de compilar y dice nullpointexception, a que se debe?

    ResponderEliminar
  16. Muchas Gracias me funcionó a la perfección.

    ResponderEliminar
  17. muchas gracias por este post amigo me sirvio de mucho, lo necesitaba para un proyecto de un juego de loteria solo que no he podido implementar tu codigo de forma que la imagen cambie de forma dinamica mediante un boton , me podrias ayudar o dar algunos consejos
    gracias de antemano.

    ResponderEliminar
  18. Como podria hacer mas pequeño el Panel donde se manda llamar la imagen?..
    intente dando un set bounds y un setSize pero no me sirvio

    ResponderEliminar
  19. Buenas noches, yo utilizo eclipse mars y me sale error poniendo ese código, pues yo tengo ya hecho el jFrame la cual tiene un menuBar y trato de poner de fondo pero no me sale nada uu Ayudenme uu es para mi proyecto uu

    ResponderEliminar
  20. Como pongo encima del fondo un Jlabel y que sea visible

    ResponderEliminar
  21. muchas gracias, fue de utilidad esta información, bendiciones

    ResponderEliminar