2010-08-04 19 views
11

Tengo una imagen que estoy rotando cuando el usuario hace clic en un botón. Pero no está funcionando.¿Cómo rotar una imagen gradualmente en Swing?

Me gustaría ver que la imagen gira gradualmente a 90 grados hasta que se detiene, pero no es así. La imagen debe girar 90 grados gradualmente cuando se hace clic en el botón.

He creado un SSCCE para demostrar el problema. Reemplace la imagen en la clase CrossingPanelSSCE con cualquier imagen que elija. Simplemente coloque la imagen en su carpeta images y asígnele el nombre images/railCrossing.JPG.

RotateButtonSSCE

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.Action; 
import javax.swing.BorderFactory; 
import javax.swing.JButton; 
import javax.swing.JPanel; 

public class RotateButtonSSCE extends JPanel implements ActionListener{ 
     private JButton rotate = new JButton("Rotate"); 
     private VisualizationPanelSSCE vis = new VisualizationPanelSSCE(); 

    public RotateButtonSSCE() { 
     this.setBorder(BorderFactory.createTitledBorder("Rotate Button ")); 
     this.rotate.addActionListener(this); 
     this.add(rotate); 
    } 

    public void actionPerformed(ActionEvent ev) { 
     vis.rotatetheCrossing(); 
    } 

} 

CrossingPanelSSCE

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.Rectangle; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.AffineTransform; 

import javax.swing.BorderFactory; 
import javax.swing.JPanel; 
import javax.swing.border.TitledBorder; 

public class CrossingPanelSSCE extends JPanel{ 

    private static final long serialVersionUID = 1L; 

    // private data members 
    private Image crossingImage; 
    private int currentRotationAngle; 
    private int imageWidth; 
    private int imageHeight; 
    private AffineTransform affineTransform; 
    private boolean clockwise; 
    private static int ROTATE_ANGLE_OFFSET = 2; 

    private int xCoordinate; 
    private int yCoordinate; 

    private static javax.swing.Timer timer; 

    private void initialize(){ 
     this.crossingImage = Toolkit.getDefaultToolkit().getImage("images/railCrossing.JPG"); 
     this.imageWidth = this.getCrossingImage().getWidth(this); 
     this.imageHeight = this.getCrossingImage().getHeight(this); 
     this.affineTransform = new AffineTransform(); 
     currentRotationAngle = 90; 
     timer = new javax.swing.Timer(20, new MoveListener()); 
    } 

    public CrossingPanelSSCE(int x, int y) { 
     this.setxCoordinate(x); 
     this.setyCoordinate(y); 
     this.setPreferredSize(new Dimension(50, 50)); 
     this.setBackground(Color.red); 
     TitledBorder border = BorderFactory.createTitledBorder("image"); 
     this.setLayout(new FlowLayout()); 
     this.initialize(); 

    } 


    public void paintComponent(Graphics grp){ 

     Rectangle rect = this.getBounds(); 
     Graphics2D g2d = (Graphics2D)grp; 
     g2d.setColor(Color.BLACK); 
     this.getAffineTransform().setToTranslation(this.getxCoordinate(), this.getyCoordinate()); 

      //rotate with the rotation point as the mid of the image 
     this.getAffineTransform().rotate(Math.toRadians(this.getCurrentRotationAngle()), this.getCrossingImage().getWidth(this) /2, 
             this.getCrossingImage().getHeight(this)/2); 

     //draw the image using the AffineTransform 
     g2d.drawImage(this.getCrossingImage(), this.getAffineTransform(), this); 
    } 


    public void rotateCrossing(){ 
     System.out.println("CurrentRotationAngle: " + currentRotationAngle); 
     this.currentRotationAngle += ROTATE_ANGLE_OFFSET; 
     //int test = currentRotationAngle % 90; 
     if(currentRotationAngle % 90 == 0){ 
     setCurrentRotationAngle(currentRotationAngle); 
     timer.stop();   
     } 

     //repaint the image panel 
     repaint(); 
    } 


    void start() { 
     if (timer != null) { 
      timer.start(); 
     } 
    } 


    private class MoveListener implements ActionListener { 

      public void actionPerformed(ActionEvent e) { 
       rotateCrossing(); 
     } 

    } 

    public Image getCrossingImage() { 
     return crossingImage; 
    } 
    public void setCrossingImage(Image crossingImage) { 
     this.crossingImage = crossingImage; 
    } 

    public int getCurrentRotationAngle() { 
     return currentRotationAngle; 
    } 
    public void setCurrentRotationAngle(int currentRotationAngle) { 
     this.currentRotationAngle = currentRotationAngle; 
    } 

    public int getImageWidth() { 
     return imageWidth; 
    } 
    public void setImageWidth(int imageWidth) { 
     this.imageWidth = imageWidth; 
    } 

    public int getImageHeight() { 
     return imageHeight; 
    } 
    public void setImageHeight(int imageHeight) { 
     this.imageHeight = imageHeight; 
    } 

    public AffineTransform getAffineTransform() { 
     return affineTransform; 
    } 
    public void setAffineTransform(AffineTransform affineTransform) { 
     this.affineTransform = affineTransform; 
    } 

    public boolean isClockwise() { 
     return clockwise; 
    } 
    public void setClockwise(boolean clockwise) { 
     this.clockwise = clockwise; 
    } 

    public int getxCoordinate() { 
     return xCoordinate; 
    } 
    public void setxCoordinate(int xCoordinate) { 
     this.xCoordinate = xCoordinate; 
    } 

    public int getyCoordinate() { 
     return yCoordinate; 
    } 
    public void setyCoordinate(int yCoordinate) { 
     this.yCoordinate = yCoordinate; 
    } 

    public javax.swing.Timer getTimer() { 
     return timer; 
    } 
    public void setTimer(javax.swing.Timer timer) { 
     this.timer = timer; 
    } 



} 

VisualizationPanelSSCE

import gui.CrossingPanel; 
import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.Shape; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.geom.GeneralPath; 

import javax.swing.BorderFactory; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.border.TitledBorder; 

import application.Robot2; 

public class VisualizationPanelSSCE extends JPanel{ 


     //private data members 
     private GeneralPath path; 
     private Shape horizontalRail; 
     private Shape verticalRail; 
     private static int LENGTH = 350; 
     private CrossingPanelSSCE crossingP; 



     private void initializeComponents(){ 
      this.path = new GeneralPath(); 
      this.horizontalRail = this.createHorizontalRail(); 
      this.verticalRail = this.createVerticalRail(); 
      this.crossingP = new CrossingPanelSSCE(328,334); 
     } 

     public VisualizationPanelSSCE(){ 
      this.initializeComponents(); 
      this.setPreferredSize(new Dimension(400,400)); 
      TitledBorder border = BorderFactory.createTitledBorder("Rotation"); 
      this.setBorder(border); 

     } 

     public GeneralPath getPath() { 
      return path; 
     } 
     public void setPath(GeneralPath path) { 
      this.path = path; 
     } 


     private Shape createHorizontalRail(){ 
      this.getPath().moveTo(5, LENGTH); 
      this.getPath().lineTo(330, 350); 
      this.getPath().closePath(); 
      return this.getPath(); 
     } 

     private Shape createVerticalRail(){ 
      this.getPath().moveTo(350, 330); 
      this.getPath().lineTo(350,10); 
      this.getPath().closePath(); 
      return this.getPath(); 
     } 


     public void paintComponent(Graphics comp){ 
      super.paintComponent(comp); 
      Graphics2D comp2D = (Graphics2D)comp; 
      BasicStroke pen = new BasicStroke(15.0F, BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND); 

      comp2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON); 
      comp2D.setPaint(Color.black); 
      comp2D.setBackground(Color.WHITE); 
      comp2D.draw(this.horizontalRail); 
      this.crossingP.paintComponent(comp2D); 
     } 


     public CrossingPanelSSCE getCrossingP() { 
      return crossingP; 
     } 
     public void setCrossingP(CrossingPanelSSCE crossingP) { 
      this.crossingP = crossingP; 
     } 

     public void rotatetheCrossing(){ 

      Runnable rotateCrossing1 = new Runnable(){ 
       public void run() { 
        crossingP.start(); 
       } 
      }; 
      SwingUtilities.invokeLater(rotateCrossing1); 
     } 


    } 

TestGUISSCE que contiene el método principal.

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.Random; 

import javax.swing.*; 

public class TestGUISSCE{ 
    private RotateButtonSSCE rotate = new RotateButtonSSCE(); 
    private VisualizationPanelSSCE vision = new VisualizationPanelSSCE(); 

    public void createGui(){ 

     JFrame frame = new JFrame("Example"); 
     frame.setSize(new Dimension(500, 500)); 


     JPanel pane = new JPanel(); 
     pane.add(this.vision); 
     pane.add(rotate); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.add(pane); 
     frame.setVisible(true); 

    } 

    public static void main(String[] args) { 
     new TestGUISSCE().createGui(); 
    } 
} 
+0

posible duplicado de [Necesita ayuda para resolver el problema de la imagen de rotación] (http://stackoverflow.com/questions/3371227/need-help-in-solving-rotation-image-problem) – finnw

+0

Todas las clases deben estar en archivos separados Publiqué una respuesta y me dieron -1. No entiendo lo que significa el -1. –

+0

@Kap: lea esto: http://stackoverflow.com/faq – BalusC

Respuesta

4
this.crossingP.paintComponent(comp2D); 

Nunca hacer esto! Su CrossingPane no se agrega a ningún componente, por lo que repinta() no tiene ningún efecto. Puede verificarlo agregando copias en el método paintComponent(). Así que hay que añadir a la CrossingPane VisualizationPane:

setLayout(new BorderLayout()); 
add(crossingP, BorderLayout.CENTER); 

Hay algunos problemas con el centrado de la imagen, pero esto no debería ser difícil de solucionar.

PS. Lea de nuevo sobre diseños y pintura.

24

Además de las observaciones votos de @ tulskiy, añadiría dos puntos:

  1. construir siempre su interfaz gráfica de usuario en el event dispatch thread, como se muestra a continuación.

  2. Un sscce debería ser un corto, Self Contained, correcta (compilable), Ejemplo. Para su comodidad, no es necesario que otros recreen múltiples clases públicas; usa clases de nivel superior (paquete privado) o anidadas. Como se trata de un problema de gráficos, use una imagen pública o sintética que refleje su problema.

En el siguiente ejemplo, paintComponent() altera el contexto de gráficos transforman para efectuar la rotación. Tenga en cuenta que las operaciones se realizan en el (aparente) reverso del orden de declaración: Primero, el centro de la imagen se traduce al origen; segundo, la imagen gira; tercero, el centro de la imagen se traduce al centro del panel. Puede ver el efecto cambiando el tamaño del panel.

Adición: Vea también esta alternativa approach usando AffineTransform.

image

package overflow; 

import java.awt.*; 
import java.awt.event.*; 
import java.awt.image.BufferedImage; 
import java.util.Random; 
import javax.swing.*; 

/** 
* @see https://stackoverflow.com/questions/3371227 
* @see https://stackoverflow.com/questions/3405799 
*/ 
public class RotateApp { 

    private static final int N = 3; 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       JFrame frame = new JFrame(); 
       frame.setLayout(new GridLayout(N, N, N, N)); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       for (int i = 0; i < N * N; i++) { 
        frame.add(new RotatePanel()); 
       } 
       frame.pack(); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 


class RotatePanel extends JPanel implements ActionListener { 

    private static final int SIZE = 256; 
    private static double DELTA_THETA = Math.PI/90; 
    private final Timer timer = new Timer(25, this); 
    private Image image = RotatableImage.getImage(SIZE); 
    private double dt = DELTA_THETA; 
    private double theta; 

    public RotatePanel() { 
     this.setBackground(Color.lightGray); 
     this.setPreferredSize(new Dimension(
      image.getWidth(null), image.getHeight(null))); 
     this.addMouseListener(new MouseAdapter() { 

      @Override 
      public void mousePressed(MouseEvent e) { 
       image = RotatableImage.getImage(SIZE); 
       dt = -dt; 
      } 
     }); 
     timer.start(); 
    } 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2d = (Graphics2D) g; 
     g2d.translate(this.getWidth()/2, this.getHeight()/2); 
     g2d.rotate(theta); 
     g2d.translate(-image.getWidth(this)/2, -image.getHeight(this)/2); 
     g2d.drawImage(image, 0, 0, null); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 
     theta += dt; 
     repaint(); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(SIZE, SIZE); 
    } 

} 

class RotatableImage { 

    private static final Random r = new Random(); 

    static public Image getImage(int size) { 
     BufferedImage bi = new BufferedImage(
      size, size, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2d = bi.createGraphics(); 
     g2d.setRenderingHint(
      RenderingHints.KEY_ANTIALIASING, 
      RenderingHints.VALUE_ANTIALIAS_ON); 
     g2d.setPaint(Color.getHSBColor(r.nextFloat(), 1, 1)); 
     g2d.setStroke(new BasicStroke(size/8)); 
     g2d.drawLine(0, size/2, size, size/2); 
     g2d.drawLine(size/2, 0, size/2, size); 
     g2d.dispose(); 
     return bi; 
    } 
} 
+0

Gracias por su publicación. Lo aprecio. –

+0

+1 agradable:) ..... –

+0

@trashgod: ¡Absolutamente WOW! + 100! – ron

5

El código para Rotated Icon utiliza el AffineTransform para girar alrededor de su centro.

+0

+1 Este es también un buen ejemplo de implementación de' Interfaz del ícono – trashgod

+0

@trashgod, Ups, publiqué en este hilo por error. Quise responder en esta publicación (http://stackoverflow.com/questions/5722058/rotate-a-picture-around-its-center/5722166#5722166). Pero veo que tiene la respuesta cubierta con dos ejemplos. – camickr

+1

¡Lo más fortuito! Complementa mi respuesta muy bien, y he agregado un enlace arriba. La pregunta puede haber sido abandonada, pero voy a azotar las respuestas por un tiempo, todavía. :-) – trashgod

Cuestiones relacionadas