Ventanas transparentes en java

El presente post muestra un interesante articulo de como generar ventanas transparentes para darle una forma diferente a la típica ventana o Frame cuadrado que siempre empleamos en nuestra programación.

Aquí les pongo el link que muestra como realizar este tipo de programación pero sus ejemplos no funcionan correctamente así que voy a detallar el código modificado que he creado para poder entenderlo mejor mas adelante.. oops bueno aqui esta la url:

http://www.onjava.com/pub/a/onjava/excerpt/swinghks_hack41/index.html

Crear translucent y shaped windows, evitando el código nativo, con uso inteligente del screenshot

Una de los mas comúnmente pedidos de características de swing es las ventanas transparentes. también llamadas shaped windows, con ventanas que tienen porciones transparentes, permitiendo ver el background del Escritorio y otros programas atraves de ellas. Java no proporciona ninguna forma de crear ventanas transparentes sin hacer uso de la Interface Nativa Java (JNI) (aunque son plataforma nativa debería apoyar la transparencia muy bien), pero eso no va a detenernos. Nosotros podemos hacerlo usando una de mis técnicas favoritas, el screeshot o captura de pantalla. El proceso de imitar una ventana transparente es básicamente:

  1. Crear un screenshot antes de mostrar la ventana.
  2. Usar ese screenshot como fondo(background) de la ventana.
  3. Ajustar la posición el screenshot con la linea superior de la pantalla real, crea la ilusión de transparencia.

Esta el la parte fácil. La parte dificil es actualizar el screenshot cuando la ventana se mueve o cambia. To start off, crear una subclase JPanel que puede capturar la pantalla y dibujarla como el background. como se muestra en el ejemplo

Ejemplo:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentListener;
import java.awt.event.ComponentEvent;

public class TransparentBackground extends JComponent {
private JFrame frame;
private Image background;

public TransparentBackground(JFrame frame) {
this.frame = frame;
updateBackground( );
}

public void updateBackground( ) {
try {
Robot rbt = new Robot( );
Toolkit tk = Toolkit.getDefaultToolkit( );
Dimension dim = tk.getScreenSize( );
background = rbt.createScreenCapture(
new Rectangle(0,0,(int)dim.getWidth( ),
(int)dim.getHeight( )));
} catch (Exception ex) {
ex.printStackTrace( );
}
}
public void paintComponent(Graphics g) {
Point pos = this.getLocationOnScreen( );
Point offset = new Point(-pos.x,-pos.y);
g.drawImage(background,offset.x,offset.y,null);
}
public static void main(String[] args) {
JFrame frame = new JFrame(“Ventana Transparente”);
TransparentBackground bg = new TransparentBackground(frame);
bg.setLayout(new BorderLayout( ));
JButton button = new JButton(“Esto es un boton”);
bg.add(“North”,button);
JLabel label = new JLabel(“Esta es una etiqueta”);
bg.add(“South”,label);
frame.getContentPane( ).add(“Center”,bg);
frame.pack( );
frame.setSize(450,400);
frame.setVisible(true);
}
}

Ejecutalo funciona de forma interesante.

Espero les sea de utilidad !!!

Anuncios

24 comentarios en “Ventanas transparentes en java

  1. Lo he probado : consigue la transparencia al mostrarse
    pero si lo arrastro queda la imagen de fondo(aun implementando ComponentListener y llmamdo al metodo updateBackground( ) en componentMove)
    y en realidad no se ha conseguido que el formulario pueda
    ser realmete transparente porque no se puede realizar accion detras del formulario
    lo ideal seria cortarlo anuestro gusto .. auq todavia no he encontrado la forma de hacerlo

  2. Realmente está muy bueno el código, y tú referencias, al igual que el que opina acá arriba, que al arrastrarlo queda la imagen de fondo, pues lo único que hice fue un repaint, y funciono.

    public void paintComponent(Graphics g) {
    Point pos = this.getLocationOnScreen( );
    Point offset = new Point(-pos.x,-pos.y);
    g.drawImage(background,offset.x,offset.y,null);
    repaint();
    }

  3. Funciona muy bien! Ademas, yo queria que capturara el fondo del momento, no solo la ventana de Java. Le agregue un updateBackground() y funciona, pero excesivamente lento, y aparece un fondo gris muy seguido. Alguno probo? Le paso algo similar? Como creen que se puede solucionar este problema?

  4. APENAS ESTOY INICIANDO EL TEMA DE VANTANAS ESTUDIO ING EN SISTEMAS Y VOY EN PRIMER SEMESTRE A MI Y A MI AMIGO BETO NOS MARCA ERRORES QUISIERAMOS SABER PORQ
    LO UNICO Q HICIMOS FUE COPIARLO Y PEGARLO
    DIGANOS SI NOS FALTA INSTALAR ALGO??

    GRACIAS Y ESTA MUY PADRE SU MATERIAL

    SALUDOS AL ITSH Y A BETO JEJEJE

  5. *CRISTINA ROMERO ROJAS
    El error está en que debes cambiar las comillas de este codigo por “” ya que estas de este codigo son diferentes ”” y no las acepta java como Strings, eso es lo unico y que la clase que crees se llame igual a la de este codigo.

  6. RESPONDER A CRISTINA ROMERO:

    TIENES QUE CAMBIAR TODAS LAS COMILLAS POR LAS DEL PROGRAMA, Y LO GUARDAS CON EL NOMBRE DE TransparentBackground……. ESPERO ME HAYAS ENTENDIDO

    AHHHH Y PARA EL AUTOR DE ESTE CODIGO ESTA MUY BIEN……PERO OPINO LO MISMO QUE LOS DEMAS AL ARRASTRARLO QUEDA LA IMAGEN DE FONDO

  7. Hola a todos, interesante tema. Un problema es que la captura de fondo la hace en el momento que se crea la ventana, y si este fondo cambia la ventana no hace una nueva captura de pantalla. Alguna idea de como solucionarlo?

  8. Esta muy bueno el ejemplo…….y si es funcional con lo que dijo Oscar Iván Rada Osorio; de poner el Repaint………ok; lo unico que les izo falta es cerrar la ventana….ya que se cierra..pero sigue ejecutandose; para esto solo es de agregar un : frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    CODIGO FUNCIONAL:

    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.ComponentListener;
    import java.awt.event.ComponentEvent;

    public class TransparentBackground extends JComponent {
    private JFrame frame;
    private Image background;

    public TransparentBackground(JFrame frame) {
    this.frame = frame;
    updateBackground( );
    }

    public void updateBackground( ) {
    try {
    Robot rbt = new Robot( );
    Toolkit tk = Toolkit.getDefaultToolkit( );
    Dimension dim = tk.getScreenSize( );
    background = rbt.createScreenCapture(
    new Rectangle(0,0,(int)dim.getWidth( ),
    (int)dim.getHeight( )));
    } catch (Exception ex) {
    ex.printStackTrace( );
    }
    }
    public void paintComponent(Graphics g) {
    Point pos = this.getLocationOnScreen( );
    Point offset = new Point(-pos.x,-pos.y);
    g.drawImage(background,offset.x,offset.y,null);
    repaint();
    }
    public static void main(String[] args) {
    JFrame frame = new JFrame(“Ventana Transparente”);
    TransparentBackground bg = new TransparentBackground(frame);
    bg.setLayout(new BorderLayout( ));
    JButton button = new JButton(“Esto es un boton”);
    bg.add(“North”,button);
    JLabel label = new JLabel(“Esta es una etiqueta”);
    bg.add(“South”,label);
    frame.getContentPane( ).add(“Center”,bg);
    frame.pack( );
    frame.setSize(450,400);
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    }

  9. Holaaaa!!! io ya tengo buen tiempo en java asiesk ya conocia esto lo use para sorprender a una amia jejeje. Pero en fin mi comentario va hacia esto:
    1. Tomar screen del escritorio es buena idea pero se perjudica cuando abres otra ventana y esta no aparece en tu “transparecnia”, esto se soluciona crenado un hilo que monitoree la ejecucion de un nuevo programa en el SO y realizando una nueva captura para actualizar el background.
    2. Para cortar el frame de verdad se necesita usar JNI y como que la cosa funciona bien hasta cierto punto.
    3. Para los que les sale demasiado el fondo gris ese cambien esta linea por:
    * g.drawImage(background,offset.x,offset.y,null);
    * g.drawImage(background,offset.x,offset.y,this);
    Esto sucede porque los cambios sucedidos en el movimiento del frame no son comunicados correctamente al Manager del paint (que este caso es tu componente), cuando colocamos “this” en esa linea estamos diciendole que los cambios sean comicados al mismo componente, usamos “this” porque el metodo “drawImage” de la clase Graphics requiere de un imageObserver y esta interfaz es implementada en la clase Component (esta clase esta en la linea de herencia de JComponent).
    4. El repaint deberia ir en los eventos de resizado, movimiento y ademas en los metodos del WindowListener para un mejor y correcto funcionamiento, ponerlo dentro del paintComponent no es muy adecuado que digamos.

    Gueno eso es todo y gracias por dejarme comentar XD!!!!

    Salu2!!!!!!!!!!!

  10. Me estoy iniciando en este mundo del Swing y necesito saber como quedaria el codigo para poner un boton transparente. Lo que pasa es que estoy haciendo una programita y cuando le pongo un icono al boton, me sale tambien un cuadrado de marca, y no hace contraste con el fondo ni auque le ponga el mismo color.

  11. Hola a todos! Me van a perdonar la ignorancia pero quisiera saber en donde puedo pegar este código para que me funcione… hay que pegarlo en en html (si es aquí de que forma) donde esta el applet o en el código de la api (si es aquí de que forma)… la verdad no se que hacer… Gracias por la ayud

  12. que pasa si yo abro la ventana sobre un video, por ejemplo, de youtube. el fondo quedaría estático. La idea es que el video se reproduzca a través de la ventana de java.

    existe alguna forma de “mirar” a través del programa? o sea, de ver lo que hay detrás de mi ventana en java?

    saludos, gracias

    Rene T.

    • utiliza:
      com.sun.awt.AWTUtilities.setWindowOpacity(this, 0.90f);
      o podes utilizar:
      com.sun.awt.AWTUtilities.setWindowOpaque(false);
      pero para ello necesitas descargar jaca update 7

  13. gracias por el aporte lo estaba buscando y de paso no se si saben como implementar los botones trasparentes osea que solo se ponga la imagen que uno quiera y la pulsen les agradeceria y si me pueden ayudar con algunas cosas gracias soy estudiante de 2 semestre de Ing de sistemas.

  14. Muy bueno este post la verdad es que me sirvio de mucho, pero ya que soy ignorante para los formularios no se si alguien sabe como cambiar la forma del formulario, supongamos que no sea cuadrad sino circular o un diseño propio, se que hay como hacer en c# pero quiciera hacerlo en netbeans… sabe alguien???… gracias con todo

  15. Hola queria decirles que esta muy bueno todo pero aun sige con una falla si ejecutamos se ve transparente “sierto”, el error esta en que al si existe otro programa habierto y esta detras, al minimizar el programa que esta detras aun sigue en el programa ejecutado mostrando la transparencia pero se ve el programa que se minimizo. alguno sabe como se podria arreglar eso??.

  16. Tengo 2 años manejando Java y ya habia escuhado algo de transparencias pero no tenia algo en concreto, el codigo funciona perfectamente y lo que comenta Makoto Hirasaca es muy cierto en cuanto a el manejo de hilos.

    ¡Muy buen aporte! esto estoy seguro ayudara a mucha gente que este interesada en este hermoso mundo de la programacion. Muchas gracias.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s