Sigueme en Facebook Sigueme en Twitter Sigueme en Instagram Sigueme en Youtube
JC Mouse Bolivia
Index / Java / Crea un efecto Flip en java swing

Crea un efecto Flip en java swing

Autor jc mouse lunes, octubre 5, 2015

Entre los correos y mensajes en facebook y whatsapp que me llegan (y de entrada pido perdón a quienes no puedo responder o me olvide responder) me preguntaron como hacer un efecto flip (dar la vuelta) para un botón en java.

Bueno java cuenta con clases y métodos que nos permiten manipular imágenes, no son los mejores pero es lo que hay y con un poco de imaginación podemos hacer casi cualquier cosa. En el siguiente tutorial crearemos un componente swing que nos permita implementar el efecto flip con imágenes

Necesitamos

  • IDE Netbeans

Tiempo 30 minutos

Nivel: Intermedio

TUTORIAL EFECTO FLIP

Paso 1. El Proyecto

File -> New project… -> Java Class Library, en nombre de proyecto ponemos JFlip y presionamos el boton finish para terminar la creación del proyecto.

A continuación creamos la estructura del proyecto como se ve a continuación:

jflip

  • JFlip.java es una clase y es nuestro componente en si, es donde colocaremos el código necesario para el efecto flip
  • DemoFrame.java es un JFrame y nos servirá para probar nuestro swing
  • resource/ es un paquete, ahí colocaremos las imágenes que usemos en el proyecto

Paso 2. Flip

Abre la clase JFlip:

package com.bolivia.flip;

public class JFlip {
    
}

La clase JFlip se extenderá de la clase JComponent, esta clase es la base de todas los componentes swing exceptuando algunos casos. Al extender de la clase JComponent tenemos la base perfecta para desarrollar nuestro swing.

Así también necesitamos controlar eventos del mouse por lo que implementaremos un MouseListener, nuestra clase queda de la siguiente forma:

import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComponent;

public class JFlip extends JComponent implements MouseListener{

    /**Constructor de clase*/
    public JFlip(){}
    
    @Override
    public void mouseClicked(MouseEvent e) {/*...*/}

    @Override
    public void mousePressed(MouseEvent e) {/*...*/}

    @Override
    public void mouseReleased(MouseEvent e) {/*...*/}

    @Override
    public void mouseEntered(MouseEvent e) {/*...*/}

    @Override
    public void mouseExited(MouseEvent e) {/*...*/}
    
}

Antes de continuar con la codificación, debemos analizar como emular en dos dimensiones el «efecto flip» siendo que en la realidad ese efecto se produce en tres dimensiones. El problema se reduce a un efecto de perspectiva es decir cuando el plano da vuelta a nuestros ojos un lado se hace más pequeño a medida que gira hasta desaparecer y reaparecer del otro lado pero esta vez aumentando de tamaño hasta alcanzar su tamaño original, en las imágenes siguientes podemos ver gráficamente a que me refiero:

flip perspective

dar la vuelta

Nuestro plano que es un polígono tiene 4 esquinas (A,B,C y D) , los puntos Ax, Cx, Bx y Dx tienen un desplazamiento horizontal uniforme hacia la mitad del plano, los puntos Ay y Cy son constantes, en cambio los puntos By y Dy tienen un movimiento vertical uniforme menor al desplazamiento horizontal, es menor porque no queremos que los puntos By y Dy se intercepten lo que arruinaría el efecto flip. Cuando los puntos Ax, Cx, Bx y Dx llegan hasta la mitad del plano, se debe invertir el procedimiento, es decir, los puntos Ax, Cx, Bx y Dx tienen ahora un desplazamiento negativo y el desplazamiento vertical también lo es, pero, las variables By y Dy se vuelven constantes y Ay y Cy son los que se desplazan en sentido vertical . Es decir:

java swing flip

Otro punto importante a considerar es que java nos permite recortar pedazos de una imagen pero esos pedazos deben ser rectangulares, por lo que no podremos hacer uso de esos métodos en este proyecto, sin embargo si podemos usar un objeto Shape para pintar secciones irregulares de una imagen usando las coordenadas del polígono descrito más arriba y así simular el efecto en perspectiva, no es lo ideal pero gracias al movimiento constante nuestros ojos no notaran la diferencia.

dog

Continuemos con la programación

Los imports que usamos en la clase flip son:

import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.GeneralPath;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.Timer;

Declaramos las variables:

    private Timer timer                     =       null;    
    private boolean inTransition            =       false;
    private int speed                       =       12;//velocidad de flip en milisegundos
    private int displacement                =       2;//desplazamiento en pixeles
    private boolean isFront                 =       true;
    private boolean inward                  =       true;//sentido del desplazamiento
    //iconos por defecto
    private Icon iconBack                   =       new ImageIcon(getClass().getResource("/com/bolivia/resource/photo1.jpg"));
    private Icon iconFront                  =       new ImageIcon(getClass().getResource("/com/bolivia/resource/photo2.jpg"));
    private Image image                     =       ((ImageIcon)iconFront).getImage();
    //variables de desplazamiento
    private int displacementHorizontal      =       0;    
    private float displacementLeft          =       0;       
    private float displacementRight         =       0;    
    //tamaño por defecto
    private Dimension dimension             =       new Dimension(160,160);

OJO: Utilizaremos dos imágenes de 160×160 pixeles que colocaremos en el paquete /resource/

A continuación declaramos el constructor de clase, sobreescribimos el método paintComponent() y definimos el método flipAnimate() para los cambios de variable de desplazamiento

    /**Constructor de clase*/
    public JFlip(){
        super();
        setSize(dimension);
        setPreferredSize(dimension);        
        setVisible(true);        
        addMouseListener(JFlip.this);        
    }
    
    @Override
    public void paintComponent(Graphics g){         
        Graphics2D g2 =(Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);            
        g2.setStroke(new BasicStroke( 0f ));
        //coordenas de imagen
        GeneralPath p = new GeneralPath();
            p.moveTo(displacementHorizontal, displacementLeft);//esquina A
            p.lineTo(getWidth()-displacementHorizontal-1, displacementRight);//esquina B
            p.lineTo(getWidth()-displacementHorizontal-1, getHeight()-displacementRight-1);//esquina D
            p.lineTo( displacementHorizontal, getHeight()-displacementLeft-1  );//esquina C
            p.closePath();
        Shape shp = p;
        g2.setClip(shp);
        g2.drawImage(image, 0, 0,getWidth() - displacementHorizontal,getHeight(), null);        
        g2.setClip(null);
        g2.draw(shp);
        g.dispose(); 
    }

    /**
     * Metodo que realiza los cambios en las variables de desplazamiento
     * @return Void
     */
    private void flipAnimate(){
        inTransition = !inTransition;
        //declaramos un evento para modificar el desplazamiento vertical y horizontal
        ActionListener animation = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                
                if(inward){   
                    displacementHorizontal += displacement;   
                    displacementRight += (displacementRight>=getHeight()/2)?0:displacement/(getSize().getWidth()/getSize().getHeight()+1f);                                        
                }else{
                    displacementHorizontal -= displacement;                                        
                    displacementLeft -=displacement/(getSize().getWidth()/getSize().getHeight()+1f);                                        
                }
                //repinta graficos
                repaint();
                
                //si se llego al medio del componente -> cambia de sentido
                if(displacementHorizontal >= getWidth()/2){ 
                    inward = false;
                    displacementLeft = displacementRight;                    
                    displacementRight=0;                    
                    //
                    if( isFront ){//mostrar imagen de atras
                        isFront=false;
                        image=((ImageIcon)iconBack).getImage();                        
                    }else{//mostrar imagen de adelante
                        isFront =true;
                        image=((ImageIcon)iconFront).getImage();                        
                    }                    
                } 
                //volvio a su posicion inicial -> detener animacion
                if( inward == false && displacementHorizontal == 0 ){
                    inTransition=false;   
                    timer.stop();
                    displacementLeft=0;
                    displacementRight=0;
                    displacementHorizontal=0;
                    inward = true;                                 
                }
            }
        }; 
        //
        if( inTransition )
        {
            if(timer != null)timer.stop();
            timer = new Timer( speed, animation);
            timer.start(); //inicia animacion      
        }
    }

El efecto flip se llevara a cabo cuando el usuario de un clic sobre el swing, por lo que debemos invocar al metodo flipAnimate() en el evento mouseClicked, nuestra clase final queda de la siguiente forma:

package com.bolivia.flip;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.GeneralPath;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.Timer;
/**
 * @web https://www.jc-mouse.net/
 * @author Mouse
 */
public class JFlip extends JComponent implements MouseListener {
    
    private Timer timer                     =       null;    
    private boolean inTransition            =       false;
    private int speed                       =       4;//velocidad de flip en milisegundos
    private int displacement                =       2;//desplazamiento en pixeles
    private boolean isFront                 =       true;
    private boolean inward                  =       true;//sentido del desplazamiento
    //iconos por defecto
    private Icon iconBack                   =       new ImageIcon(getClass().getResource("/com/bolivia/resource/photo1.jpg"));
    private Icon iconFront                  =       new ImageIcon(getClass().getResource("/com/bolivia/resource/photo2.jpg"));
    private Image image                     =       ((ImageIcon)iconFront).getImage();
    //variables de desplazamiento
    private int displacementHorizontal      =       0;    
    private float displacementLeft          =       0;       
    private float displacementRight         =       0;    
    //tamaño por defecto
    private Dimension dimension             =       new Dimension(160,160);
    
    /**Constructor de clase*/
    public JFlip(){
        super();
        setSize(dimension);
        setPreferredSize(dimension);        
        setVisible(true);        
        addMouseListener(JFlip.this);        
    }
    
    @Override
    public void paintComponent(Graphics g){         
        Graphics2D g2 =(Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);            
        g2.setStroke(new BasicStroke( 0f ));
        //coordenas de imagen
        GeneralPath p = new GeneralPath();
            p.moveTo(displacementHorizontal, displacementLeft);//esquina A
            p.lineTo(getWidth()-displacementHorizontal-1, displacementRight);//esquina B
            p.lineTo(getWidth()-displacementHorizontal-1, getHeight()-displacementRight-1);//esquina D
            p.lineTo( displacementHorizontal, getHeight()-displacementLeft-1  );//esquina C
            p.closePath();
        Shape shp = p;
        g2.setClip(shp);
        g2.drawImage(image, 0, 0,getWidth() - displacementHorizontal,getHeight(), null);        
        g2.setClip(null);
        g2.draw(shp);
        g.dispose(); 
    }

    /**
     * Metodo que realiza los cambios en las variables de desplazamiento
     * @return Void
     */
    private void flipAnimate(){
        inTransition = !inTransition;
        //declaramos un evento para modificar el desplazamiento vertical y horizontal
        ActionListener animation = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent ae) {
                
                if(inward){   
                    displacementHorizontal += displacement;   
                    displacementRight += (displacementRight>=getHeight()/2)?0:displacement/(getSize().getWidth()/getSize().getHeight()+1f);                                        
                }else{
                    displacementHorizontal -= displacement;                                        
                    displacementLeft -=displacement/(getSize().getWidth()/getSize().getHeight()+1f);                                        
                }
                //repinta graficos
                repaint();
                
                //si se llego al medio del componente -> cambia de sentido
                if(displacementHorizontal >= getWidth()/2){ 
                    inward = false;
                    displacementLeft = displacementRight;                    
                    displacementRight=0;                    
                    //
                    if( isFront ){//mostrar imagen de atras
                        isFront=false;
                        image=((ImageIcon)iconBack).getImage();                        
                    }else{//mostrar imagen de adelante
                        isFront =true;
                        image=((ImageIcon)iconFront).getImage();                        
                    }                    
                } 
                //volvio a su posicion inicial -> detener animacion
                if( inward == false && displacementHorizontal == 0 ){
                    inTransition=false;   
                    timer.stop();
                    displacementLeft=0;
                    displacementRight=0;
                    displacementHorizontal=0;
                    inward = true;                                 
                }
            }
        }; 
        //
        if( inTransition )
        {
            if(timer != null)timer.stop();
            timer = new Timer( speed, animation);
            timer.start(); //inicia animacion      
        }
    }
    
    @Override
    public void mouseClicked(MouseEvent e) {
        flipAnimate();
    }

    @Override
    public void mousePressed(MouseEvent e) {/*...*/}

    @Override
    public void mouseReleased(MouseEvent e) {/*...*/}

    @Override
    public void mouseEntered(MouseEvent e) {/*...*/}

    @Override
    public void mouseExited(MouseEvent e) {/*...*/}

    public Icon getIconBack() {
        return iconBack;
    }

    public void setIconBack(Icon iconBack) {
        this.iconBack = iconBack;
    }

    public Icon getIconFront() {
        return iconFront;
    }

    public void setIconFront(Icon iconFront) {
        this.iconFront = iconFront;
    }

    public int getDisplacement() {
        return displacement;
    }

    public void setDisplacement(int displacement) {
        this.displacement = displacement;
    }

    public int getSpeed() {
        return speed;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }
    
}//JFlip:end

Compilamos el proyecto, para usar el componente solo lo arrastramos al jframe y también podemos modificar la velocidad de animación, la cantidad de desplazamiento en pixeles y cargar nuevas imagenes desde su menú de propiedades, ejecutamos y probamos el efecto flip.

Descargar proyecto FLIP aquí 🙂

enjoy!!!

Tags

Si te ha gustado podrías compartirlo o dejar un comentario. ¡Muchas gracias!
Autor: JC Mouse

Yo soy yo :) JC Mouse, Soy orgullosamente boliviano soy fundador y CEO de la web jc-Mouse.net uno de las pocas web en emprendimiento y tecnología en Bolivia.

Toda la información que encuentres en este sitio es y sera completamente gratis siempre, puedes copiar, descargar y re-publicar si así lo deseas en otros blogs o sitios web, solo te pido a cambio que dejes una referencia a esta web. Esto nos ayuda a crecer y seguir aportando. Bye

Enjoy! :)

También Te Podría Interesar

Reportes con imagenes en Java (Video)

Reportes con imagenes en Java (Video)

Video Tutorial que muestra una de las maneras de utilizar y mostrar imagenes en iReport, pasando estas como parametros d...

Empaquetado de texturas en LibGDX

Empaquetado de texturas en LibGDX

Continuando con los tutoriales sobre LibGDX (Librería para el desarrollo de videojuegos), en esta ocasión veremos como e...

Construye tu aplicación de mensajeria

Construye tu aplicación de mensajeria

En este post crearemos una aplicación sencilla para mandar mensajes de texto desde android. Necesitamos IDE: Eclipse + S...

Mapas HTML5 – Elementos del canvas- Parte 4

Mapas HTML5 – Elementos del canvas- Parte 4

Continuando con nuestro tutorial de «Mapas interactivos con HTML5» , esta es la sección que corresponde a los elementos...

Informes Access con JasperReport/iReport

Informes Access con JasperReport/iReport

En este post vemos la forma de conectar una base de datos Access con JasperReport para diseñar y ejecutar reportes. Para...

Animación con sprites y LibGDX

Animación con sprites y LibGDX

En este post veremos una pequeña introducción a lo que son las animaciones con LibGDX y el uso de sprites. ¿Que es la an...

Comparte lo que sabes

Categorias

Últimas entradas

Si trabajas con redes sociales (RRSS) a continuación te muestro tres herramintas gratuitas que te ayudaran a la hora de...

Por lo general se usan transacciones a nivel base de datos y posteriormente se llaman estos a través de procedimientos a...

En este post, aprenderemos como conectar Visual Basic 6 con SQL Server, abrir una tabla, leer su contenido y mostrar est...

Lo que veremos en este post es la configuración del driver para PHP de SQL Server que ha creado Microsoft el cual permit...

Herramientas

Generador de Enlaces a Whatsapp