7

first of all, this is the first week that I use swing, then sorry if my question is too obvious. Also, I need solutions that use the standard java libraries, since this is for homework and I'm not allowed to use strange libraries.

I'm using JLabel with ImageIcon to show images on a JFrame. Now I want to rotate the image on screen to arbitrary angles. I found something about Graphics2D but i don't find the way to do that.

Since solutions that I found doesn't work or I don't understand them, I'm interested in any solution to rotate the ImageIcon or the JLabel. Since I'm positioning the image doing setBounds on the JLabel, rotate the JLabel will be a better solution I think (this way I'm not forced to save the ImageIcon object too).

Thank you for your attention and sorry for my bad English.

Edit... To show the image in screen I do the next:

JFrame frame = new JFrame("Something");
frame.setLayout(new FlowLayout()); //for example
JPanel panel = new JPanel();
panel.setLayout(null);

ImageIcon playerSprite = new ImageIcon("rute/to/file.png");
JLabel player = new JLabel(playerSprite);

panel.add(player);
player.setBounds(10,10,36,52); //for example

frame.getContentPane().add(panel);
frame.setVisible(true);

Resuming, how can I rotate this IconImage or the JLabel. I can use other method to show the image if you think that is better. If the solution is use Graphics2D, like I see, I will appreciate a solution to arrive to an object of this class an later return the rotated image to an ImageIcon, because when I try this...

ImageIcon imagePlayer = new ImageIcon("img/stand.png");
Image image = imagePlayer.getImage();
Graphics2D g = (Graphics2D)image.getGraphics();

At execution time, the answer is this...

Exception in thread "main" java.lang.UnsupportedOperationException: getGraphics() not valid for images created with createImage(producer)

2th edition... Now I'm working with this code. The image rotates but the old unrotated image still remains on screen under the new one. Put a png image called stand.png on the same directory and you will see it.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.Math;
public class Test {
    public static void main(String args[]) throws Exception {    
        try {
            JFrame frame = new JFrame("Rotation Test");
            frame.setBounds(10,10,1008,756);

            BufferedImage bi = ImageIO.read(new File("stand.png"));
            Graphics2D g = (Graphics2D)bi.getGraphics();
            g.rotate(Math.toRadians(45),26,26);
            g.drawImage(bi, 0, 0, null);
            JLabel player = new JLabel(new ImageIcon(bi));
            frame.getContentPane().add(player);

            player.setBounds(0,0,100,100);
            frame.setVisible(true);
        } catch (IOException ex) {
            System.out.println("Exception");
        }
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
dgnin
  • 1,565
  • 2
  • 20
  • 33
  • +1 for a compilable example; as an exercise, try making it complete using my example's `RotatableImage.getImage()` or @camickr's `Rotated Icon`. – trashgod Nov 27 '10 at 20:10

2 Answers2

11

Instead of rotating the component itself, consider rotating the content of a component. This example draws a rotated image in a JPanel.

Addendum: In the example RotatableImage.getImage() creates a BufferedImage directly in memory, but you can use ImageIO.read() to obtain an image from elsewhere. BufferedImage#createGraphics() is supported if you want to modify the image, but you probably just want to draw the unmodified image in a rotated graphics context as part of paintComponent().

Addendum: You're painting over the image with a rotated copy; instead, draw the image into a rotated graphics context:

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    public static void main(String args[]) throws Exception {
        JFrame frame = new JFrame("Rotation Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final BufferedImage bi = ImageIO.read(new File("img/stand.jpg"));
        frame.add(new JPanel() {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(bi.getWidth(), bi.getHeight());
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                g2.rotate(Math.PI / 4, bi.getWidth() / 2, bi.getHeight() / 2);
                g2.drawImage(bi, 0, 0, null);
            }
        });
        frame.pack();
        frame.setVisible(true);
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I understand that the clue is use Graphics2D but in that example I don't see how to arrive to this class from an ImageIcon object. In fact, I just edited the main post to show that I recieve an exeption trying it. Thank you for your help. – dgnin Nov 27 '10 at 07:47
  • @nin1987: I've elaborated above. – trashgod Nov 27 '10 at 13:49
  • Ok, I don't understand all your code and probably there is the reason why mine fails but at least the problem is a little bit solved. I edit my first post with the new code I wrote and with it the image rotates, but the unrotated original image is also showed. I tired to create a new BufferedImage (same size and same type) and paint there the rotation but it doesn't works (paints only the original unrotated image). – dgnin Nov 27 '10 at 17:15
  • 1
    @nin1987: Excellent! Now, try varying the parameters to `rotate()` to see the effect. – trashgod Nov 28 '10 at 19:17
3

Since solutions that I found doesn't work or I don't understand them

Well, if you don't understand them, then you should post your SSCCE (http://sscce.org) demonstrating your test code. Then maybe someone will be able to explain how the code work.

I doubt you would be able to understand any new code we might post since the concepts of rotation an image or an Icon are all the same.

Since I'm positioning the image doing setBounds on the JLabel

Why are you using setBounds(). You should use a layout manager so you don't have to worry about this.

Edit:

Maybe you can use a Rotated Icon.

camickr
  • 321,443
  • 19
  • 166
  • 288
  • I have to show a Volleyball court with players moving inside, rotating, changing the sprite, etc. then I have to work with absolute positions all the time. In this situation I think that setLayout(null) is a good option, correct me if I'm wrong. – dgnin Nov 27 '10 at 07:24
  • However, I edited the main post with some examples (I hope it can be considered SSCCE :D) illustrating my problem. Thank you. – dgnin Nov 27 '10 at 07:48
  • @nin1987, how would you consider that a SSCCE? How is that code compileable? See my edit. – camickr Nov 27 '10 at 16:16
  • I have to use standard libraries. – dgnin Nov 27 '10 at 16:58
  • @nin1987, so you look at the code and understand how it works and then modify the code for your own purposes. There is no "standard libarary" that does what you want. You need to use the various methods of the standard libraries to achieve your desired goal. That is why my first suggestion said you need to post the code you have attempted to use. – camickr Nov 27 '10 at 17:04