Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
212 views
in Technique[技术] by (71.8m points)

java - getting the right image observer for rotating an image

So Im drawing a BufferedImage 'bird' but I want to rotate it according to the angle that it is falling. I have a bird object which contains the BufferedImage and a render() method which draw it rotated.

public void render(Graphics2D g, ImageObserver io) {

    double theta = Math.tan((height - pastHeight) / .875);
    System.out.println(theta);
    Graphics2D g2 = (Graphics2D) bird.getGraphics();

    g2.drawImage(bird, 100, (int) height, null);

    g2.rotate(theta);

    g2.drawImage(bird, 100, (int) height, io);
}

I call this as such

bird.render(g2, ???);

in my paintcomponent method in my jcomponent.

only problem is I dont know what to use as my ImageObserver... I've tried passing in my JFrame and my JComponent but the image no longer appears when I do that... what would I pass in for the image to appear in my window and/or how else would I achieve this rotation?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Assuming that you are doing this in something that extends JComponent, you should use

bird.render(g2, this);

As JComponent implements ImageObserver

The problem with the image disappearing isn't an issue with the ImageObserver but the point around which the rotation is occurring, which I believe is the top/left corner of the Graphics context.

Try using Graphics2D#rotate(double, int, int) which will allow you to specify the origin points of the rotation (pivot point).

Don't forget to reset your translations, as they will effect everything that is painted after your supply them and may be re-used in subsequent paint cycles.

Updated with simple example

This is a basic example that demonstrates the different uses of rotate.

First, I simply used Graphics#rotate(double)

rotate

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class RotateImage {

    public static void main(String[] args) {
        new RotateImage();
    }

    public RotateImage() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private BufferedImage img;
        private double angel = 0d;

        public TestPane() {
            try {
                img = ImageIO.read(...);
            } catch (IOException ex) {
                ex.printStackTrace();
            }

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    angel += 5;
                    repaint();
                }
            });
            timer.start();
        }

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

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.rotate(Math.toRadians(angel));
                int x = (getWidth() - img.getWidth()) / 2;
                int y = (getHeight() - img.getHeight()) / 2;
                g2d.drawImage(img, x, y, this);
                g2d.dispose();
            }
        }
    }

}

Then I replaced g2d.rotate(Math.toRadians(angel)); with g2d.rotate(Math.toRadians(angel), getWidth() / 2, getHeight() / 2);, which used the center position of the component (or the Graphics context) as the anchor point around which the rotation would occur...

center

Now, because you only want to rotate your image, you're going to need to calculate the anchor point around the current position of the image's center position (assuming you want it to rotate around the middle)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...