|
Description:
|
My previous example Creating a Image Zoomer using Graphics2D explained how to get the Grpahics2D object in the paintComponent(Graphics) method and use to perform scaling. Here the scaling transformation was performed on the entire graphics context. This example explains how to perform rotation transformation using the java.awt.geom..AffineTransform class. Package java.awt.geom provides the Java 2D classes for defining and performing operations on objects related to two-dimensional geometry. Using AffineTransform we can perform sequence of transformations on a particular object in the graphics context.
In this example we will apply a rotation transformation on an Image without affecting other objects in the context. To do this we need to create an instance of AffineTransform, then call its rotate() method with angle of rotation and draw the image by using the drawImage() method of Graphics2D class by passing the AffineTransform instance. Following is the code to do this,
//creating the AffineTransform instance
AffineTransform affineTransform = new AffineTransform();
//rotate the image
affineTransform.rotate(Math.toRadians(45));
//draw the image using the AffineTransform
g2d.drawImage(m_image, m_affineTransform, this);
The above code will rotate the image with 45 degree angle considering the anchor point as (0, 0). Anchor point is the point, which is considered to be the mid point for rotation. Also the image will be drawn at the point (0, 0).
To improvise the above code to rotate the image in such a way that the anchor point is always the center of the image we can use the method rotate(double theta, double x, double y) of the AffineTransform class. Where x, and y are the co-ordinates of the anchor point. The effect will be like the image is just tilted by 45 degrees. Following is the code for this,
//creating the AffineTransform instance
AffineTransform affineTransform = new AffineTransform();
//rotate with the anchor point as the mid of the image
affineTransform.rotate(Math.toRadians(45), m_imageWidth/2, m_imageHeight/2);
The rotated image will be drawn at the point (0, 0). To draw the image at the center of the component we can perform the translation before the rotation. Something like this.
Rectangle rect = this.getBounds();
//creating the AffineTransform instance
AffineTransform affineTransform = new AffineTransform();
//set the translation to the mid of the component
affineTransform.setToTranslation((rect.width-m_imageWidth)/2,(rect.height-m_imageHeight)/2);
//rotate with the anchor point as the mid of the image
affineTransform.rotate(Math.toRadians(45), m_imageWidth/2, m_imageHeight/2);
//draw the image using the AffineTransform
g2d.drawImage(m_image, affineTransform, this);
This will draw the rotated image at the angle of 45 degrees at the center of the component.
To rotate the image continuously we will need to set a timer and keep changing the rotation angle. To rotate a image in a complete circle in a clockwise direction the angle will keep incrementing from 0 degree to 360 degree and to rotate in a anti-clockwise direction the angle will keep decrementing from 360 degree to 0 degree.
The speed of rotation will depend upon the timer interval.
|
|
|
Example Code:
|
This example creates an Image Rotator, which rotates a selected image in a clockwise or anti-clockwise direction. The applet provides a selection for the image, takes the rotation speed in milli-seconds and provides option to select the direction. The ImageRotatorFrame creates the ImagePanel, which is extended from JPanel. The Timer is set in the ImageRotatorFrame which calls the rotate() method of the ImagePanel, which changes the image angle and gives call to repaint() method of the ImagePanel.
|
/*
* This example is from javareference.com
* for more information visit,
* http://www.javareference.com
*/
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
/**
* This class creates a Image Rotator
* @author Rahul Sapkal(rahul@javareference.com)
*/
public class ImageRotatorFrame extends JFrame implements ActionListener
{
private ImagePanel m_imagePanel;
private int m_rotateSpeed;
private Timer m_rotateTimer;
private JPanel m_imageContainer;
/**
* Constructor
*
* @param image
* @param speed
* @param imageName
* @param clockwise
*/
public ImageRotatorFrame(Image image, int speed, String imageName, boolean clockwise)
{
super("Image Rotator [" + imageName + "]");
m_rotateSpeed = speed;
if(image == null)
{
add(new JLabel("Image " + imageName + " not Found"));
}
else
{
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
String mess = "Rotation Speed : " + m_rotateSpeed + " milli-seconds";
if(clockwise)
{
mess += " in Clockwise direction";
}
else
{
mess += " in Anti-Clockwise direction";
}
topPanel.add(new JLabel(mess));
m_imagePanel = new ImagePanel(image, clockwise);
getContentPane().add(BorderLayout.NORTH, topPanel);
getContentPane().add(BorderLayout.CENTER, m_imagePanel);
m_imagePanel.repaint();
}
setSize(1000, 800);
setVisible(true);
//create the rotate timer
m_rotateTimer = new Timer(m_rotateSpeed, this);
//start the rotate timer
m_rotateTimer.start();
}
/**
* Action Listener method taking care of
* actions on the buttons
*/
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource().equals(m_rotateTimer))
{
//give call to rotate the image
m_imagePanel.rotate();
}
}
/**
* This class is the Image Panel where the image
* is drawn and rotated
*
* @author Rahul Sapkal(rahul@javareference.com)
*/
public class ImagePanel extends JPanel
{
//Offset angle for rotation
public static final int ROTATE_ANGLE_OFFSET = 5;
private Image m_image;
private int m_currentRotateAngle;
private int m_imageWidth, m_imageHeight;
private AffineTransform m_affineTransform;
private boolean m_clockwise;
/**
* Constructor
*
* @param image
* @param clockwise
*/
public ImagePanel(Image image, boolean clockwise)
{
m_clockwise = clockwise;
m_image = image;
m_imageWidth = m_image.getWidth(this);
m_imageHeight = m_image.getHeight(this);
if(!clockwise)
{
m_currentRotateAngle = 360 + ROTATE_ANGLE_OFFSET;
}
m_affineTransform = new AffineTransform();
}
/**
* This method is overriden to draw and rotate
* the image accordingly
*/
public void paintComponent(Graphics grp)
{
Rectangle rect = this.getBounds();
Graphics2D g2d = (Graphics2D)grp;
//set the background color to black
g2d.setColor(Color.BLACK);
//fill the rect
g2d.fillRect(0, 0, getWidth(), getHeight());
//set the translation to the mid of the component
m_affineTransform.setToTranslation((rect.width-m_imageWidth)/2,(rect.height-m_imageHeight)/2);
//rotate with the rotation point as the mid of the image
m_affineTransform.rotate(Math.toRadians(m_currentRotateAngle), m_imageWidth/2, m_imageHeight/2);
//draw the image using the AffineTransform
g2d.drawImage(m_image, m_affineTransform, this);
}
/**
* This method changes the rotation angle depending
* upon the selected rotation direction and repaints
* the ImagePanel
*/
public void rotate()
{
if(m_clockwise)
{
//if clockwise then increment the rotation angle
//by the offset till the angle is 360
//then again set to 0
m_currentRotateAngle += ROTATE_ANGLE_OFFSET;
//mod takes care of setting the angle to 0 if
//it is 360
m_currentRotateAngle %= 360;
}
else
{
//if anti-clockwise then decrement the rotation angle
//by the offset till the angle is equal to 0
//then again set to 360
m_currentRotateAngle -= ROTATE_ANGLE_OFFSET;
if(m_currentRotateAngle <= 0)
{
m_currentRotateAngle = 360;
}
}
//repaint the image panel
repaint();
}
}
}
--------------------------------------------------------------------------
/*
* This example is from javareference.com
* for more information visit,
* http://www.javareference.com
*/
//package
//import statements
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
* This class creates the Image Rotator applet
* @author Rahul Sapkal(rahul@javareference.com)
*/
public class ImageRotator extends JApplet implements ActionListener
{
//static variables
public static final int DEFAULT_ROTATION_SPEED = 50; //in milli-seconds
//public variables
private String images[] = {"puppy.jpg",
"ash.jpg",
"jr.gif",
"cliff.jpg",
"bridge.jpg"};
private JButton m_launch;
private JList m_imageList;
private JTextField m_rotateSpeed;
private JCheckBox m_clockwise;
public void init()
{
getContentPane().setLayout(new BorderLayout());
m_imageList = new JList(images);
m_imageList.setSelectedIndex(0);
m_launch = new JButton("Launch Image Rotator");
m_launch.addActionListener(this);
Panel input = new Panel(new FlowLayout());
input.add(m_launch);
Panel input1 = new Panel(new FlowLayout());
input1.add(new Label("Enter image rotation speed in milli-secs and rotation direction :"));
m_rotateSpeed = new JTextField(5);
m_rotateSpeed.setText(String.valueOf(DEFAULT_ROTATION_SPEED));
m_clockwise = new JCheckBox("Rotate Clockwise", true);
input1.add(m_rotateSpeed);
input1.add(m_clockwise);
getContentPane().add(BorderLayout.NORTH, input1);
getContentPane().add(BorderLayout.CENTER, m_imageList);
getContentPane().add(BorderLayout.SOUTH, input);
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource().equals(m_launch))
{
//getting the image
String imageName = ((String)(m_imageList.getSelectedValue())).trim();
Image image = getImage(getCodeBase(), imageName);
MediaTracker mt = new MediaTracker(this);
mt.addImage(image, 1);
try
{
mt.waitForAll();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
int speed = DEFAULT_ROTATION_SPEED;
try
{
speed = Integer.valueOf(m_rotateSpeed.getText().trim()).intValue();
}
catch(NumberFormatException numExp)
{
}
//create the Image Rotator frame
ImageRotatorFrame imageRotator = new ImageRotatorFrame(image, speed, imageName, m_clockwise.isSelected());
}
}
}
|
|
Demonstration:
|
The above example is demonstrated by the following applet.
Click here to see the image of the applet if it is not executing on your machine. You have to download JavaPlugin to execute this applet.
Select the image from the list and click on the Launch Image Rotator button to launch the Image Rotator frame. You can adjust the Rotation Speed by setting the value in the text box and Rotation Direction by clicking on the direction checkbox. Have Fun !!!
|
|