繁体   English   中英

如何使用 Graphics2D 旋转某些东西

[英]How to rotate something with Graphics2D

所以我想旋转我制作的这个矩形

public void paint (Graphics g)
    {
        super.paint(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.fillRect(10, 10, 30, 30);
        g2.rotate(Math.toRadians(45)); //I tried this but doesn't seem to work... 
    }

我怎么做? 旋转 45* 角或 200* 角旋转。

根据我的评论,我创建了以下 GUI。

旋转矩形

我使用数学计算旋转矩形的四个端点,并使用Graphics2D fillPolygon方法绘制矩形。

GUI 底部的按钮允许您在中心点或左上端点旋转矩形。

我创建了一个绘图JPanel来绘制矩形。 绘图JPanel的所有paintComponent方法所做的都是绘制应用程序 model 返回的Polygon

应用程序 model 是该应用程序的关键部分。 我创建了一个普通的 Java getter / setter class。 我从java.awt.Rectangle开始,并使用极坐标旋转矩形。 我将极坐标转换回笛卡尔坐标以获得Polygon的四个端点。

这是完整的可运行代码。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class RotatingRectangle implements Runnable {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new RotatingRectangle());
    }
    
    private DrawingPanel drawingPanel;
    
    private JButton centerButton;
    private JButton endPointButton;
    
    private RotatedRectangle rotatedRectangle;
    
    public RotatingRectangle() {
        this.rotatedRectangle = new RotatedRectangle(Color.BLUE, 
                new Rectangle(200, 200, 100, 50));
    }

    @Override
    public void run() {
        JFrame frame = new JFrame("Rotating Rectangle");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        this.drawingPanel = new DrawingPanel(rotatedRectangle);
        frame.add(drawingPanel, BorderLayout.CENTER);
        frame.add(createButtonPanel(), BorderLayout.AFTER_LAST_LINE);
        
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    public JPanel createButtonPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 5));
        
        ButtonListener listener = new ButtonListener(this, rotatedRectangle);
        
        centerButton = new JButton("Rotate on center point");
        centerButton.addActionListener(listener);
        panel.add(centerButton);
        
        endPointButton = new JButton("Rotate on end point");
        endPointButton.addActionListener(listener);
        endPointButton.setPreferredSize(centerButton.getPreferredSize());
        panel.add(endPointButton);
        
        return panel;
    }
    
    public void repaint() {
        drawingPanel.repaint();
    }
    
    public JButton getCenterButton() {
        return centerButton;
    }

    public JButton getEndPointButton() {
        return endPointButton;
    }

    public class DrawingPanel extends JPanel {

        private static final long serialVersionUID = 1L;
        
        private RotatedRectangle rotatedRectangle;
        
        public DrawingPanel(RotatedRectangle rotatedRectangle) {
            this.rotatedRectangle = rotatedRectangle;
            this.setBackground(Color.WHITE);
            this.setPreferredSize(new Dimension(400, 400));
        }
        
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            
            Polygon polygon = rotatedRectangle.getRectangle();
            Graphics2D g2d = (Graphics2D) g;
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
                    RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.setColor(rotatedRectangle.getColor());
            g2d.fillPolygon(polygon);
        }
        
    }
    
    public class ButtonListener implements ActionListener {
        
        private final RotatingRectangle frame;
        
        private final RotatedRectangle model;
        
        private Timer timer;

        public ButtonListener(RotatingRectangle frame, RotatedRectangle model) {
            this.frame = frame;
            this.model = model;
        }

        @Override
        public void actionPerformed(ActionEvent event) {
            if (timer != null) {
                timer.stop();
            }
            
            JButton button = (JButton) event.getSource();
            if (button.equals(frame.getEndPointButton())) {
                model.setCenterPoint(false);
                model.setAngle(180);
            } else {
                model.setCenterPoint(true);
                model.setAngle(0);
            }
            
            timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent evt) {
                    model.incrementAngle(1);
                    frame.repaint();
                }
            });
            timer.start();
        }
        
        
    }

    public class RotatedRectangle {
        
        private boolean centerPoint;
        
        private int angle;
        
        private final Color color;
        
        private final Rectangle rectangle;

        public RotatedRectangle(Color color, Rectangle rectangle) {
            this.color = color;
            this.rectangle = rectangle;
            this.angle = 0;
            this.centerPoint = true;
        }

        public int getAngle() {
            return angle;
        }

        public void setAngle(int angle) {
            this.angle = angle;
        }
        
        public void incrementAngle(int increment) {
            this.angle += increment;
            this.angle %= 360; 
        }

        public Polygon getRectangle() {
            Point rotatePoint = new Point(rectangle.x, rectangle.y);
            if (isCenterPoint()) {
                int x = rectangle.x + rectangle.width / 2;
                int y = rectangle.y + rectangle.height / 2;
                rotatePoint = new Point(x, y);
            }
            
            Point[] point = new Point[4];
            int width = rectangle.x + rectangle.width;
            int height = rectangle.y + rectangle.height;
            point[0] = new Point(rectangle.x, rectangle.y);
            point[1] = new Point(width, rectangle.y);
            point[2] = new Point(width, height);
            point[3] = new Point(rectangle.x, height);
            
            Polygon polygon = new Polygon();
            for (int i = 0; i < point.length; i++) {
                point[i] = calculatePoint(rotatePoint, point[i], angle);
                polygon.addPoint(point[i].x, point[i].y);
            }
            
            return polygon;
        }
        
        private Point calculatePoint(Point rotatePoint, Point point, int angle) {
            double theta = Math.toRadians(angle);
            int xDistance = rotatePoint.x - point.x;
            int yDistance = rotatePoint.y - point.y;
            double distance = Math.sqrt(xDistance * xDistance + yDistance * yDistance);
            double alpha = Math.atan2(yDistance, xDistance);
            
            theta += alpha;
            int x = (int) Math.round(Math.cos(theta) * distance) + rotatePoint.x;
            int y = (int) Math.round(Math.sin(theta) * distance) + rotatePoint.y;
            
            return new Point(x, y);
        }

        public Color getColor() {
            return color;
        }

        public boolean isCenterPoint() {
            return centerPoint;
        }

        public void setCenterPoint(boolean centerPoint) {
            this.centerPoint = centerPoint;
        }
        
    }
    
}

旋转对象真的不是那么难。 下面的大部分代码只是用于创建框架和面板的样板。 这是一个演示,显示了评论中提到的两种方法。

  • 左侧面板只是旋转图形上下文。 这是,imo,最简单的方法,但它不会改变 object。
  • 右侧面板使用AffineTransform旋转 object。 这实际上改变了形状的内容。

如果希望将 object 旋转到位,则有必要确保其围绕正在旋转的图像的中间进行旋转。 在这两种情况下,这将是(125,125)或面板和矩形的中心。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.border.LineBorder;

public class RotateRectangle extends JPanel {
    
    JFrame frame = new JFrame();
    double angle = 0;
    MyPanel mypanel = new MyPanel();
    public static void main(String[] args) {
        SwingUtilities
                .invokeLater(() -> new RotateRectangle().start());
    }
    
    public void start() {
        Timer t = new Timer(0, (ae) -> {mypanel.rotateit(); frame.repaint();});
        t.setDelay(30);
        t.start();
    }
    
    public RotateRectangle() {
        frame.setLayout(new FlowLayout());
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        frame.add(mypanel);
        setBorder(new LineBorder(Color.red,2));
        mypanel.setBorder(new LineBorder(Color.red, 2));
        frame.pack();
        // center on screen
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        
        // visually smooth the lines
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        
        g2d.setPaint(Color.BLACK);
        g2d.rotate(angle, 125,125);
        g2d.drawRect(75, 75, 100, 100);
        
// adjust the amount of rotation per timer interval
        angle += Math.PI / 200;
        g2d.dispose();
    }
    
    public Dimension getPreferredSize() {
        return new Dimension(250, 250);
    }
    
}

class MyPanel extends JPanel {
    Polygon polygon = new Polygon();
    // amount to rotate
    double angle = Math.PI / 200;
    Shape shape = polygon;
    AffineTransform af =  new AffineTransform();

    public MyPanel() {
        af.rotate(angle, 125,125);
        polygon.addPoint(75,175);
        polygon.addPoint(175,175);
        polygon.addPoint(175,75);
        polygon.addPoint(75,75);

    }
    public void rotateit() {
        
        shape = af.createTransformedShape(shape);
    
    }
    
    public void paintComponent(Graphics g) {
        if (shape == null) {
            return;
        }
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D)g;
        
        // visually smooth the lines
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        
        g2d.setPaint(Color.BLACK);
        g2d.draw(shape);
        
    }
    
    public Dimension getPreferredSize() {
        return new Dimension(250, 250);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM