Java 旋转JPanel中绘制的内容,保持质心的位置

Java 旋转JPanel中绘制的内容,保持质心的位置,java,swing,rotation,jpanel,awt,Java,Swing,Rotation,Jpanel,Awt,我想根据旋转角度并围绕相应面板的质心旋转在paintComponentGraphics g方法中绘制的内容 以下是我最初的想法: 控制面板textfield+按钮,用于设置角度(以度为单位),从0到359。包含一个白色小面板的主面板。当用户单击“设置角度”按钮时,必须更新小白色面板的设置边界并重新绘制。在任何情况下,小白色面板必须以其质心为中心 这是我想要的90度和135度: 这是我的SSCCE,它不工作了。你能告诉我我做错了什么吗 import java.awt.BorderLayout; i

我想根据旋转角度并围绕相应面板的质心旋转在paintComponentGraphics g方法中绘制的内容

以下是我最初的想法:

控制面板textfield+按钮,用于设置角度(以度为单位),从0到359。包含一个白色小面板的主面板。当用户单击“设置角度”按钮时,必须更新小白色面板的设置边界并重新绘制。在任何情况下,小白色面板必须以其质心为中心

这是我想要的90度和135度:

这是我的SSCCE,它不工作了。你能告诉我我做错了什么吗

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class RotatingPaint {
    private static double angle = 0;
    private static JFrame frame = new JFrame();
    private static JTextField angleField = new JTextField("0", 6);
    private static JButton angleButton = new JButton("Set angle");
    private static JPanel controlPanel = new JPanel();
    private static JPanel mainPanel  = new JPanel();
    private static JPanel littleWhitePanel  = new JPanel() {
        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g;
            Color oldColor = g2.getColor();
            g2.setColor(Color.RED);
            g2.rotate(angle, getWidth() / 2, getHeight() / 2);
            g2.drawString("Hello World", 2, 12);
            // Revert the transformation matrix back to its initial state
            g2.rotate(-angle, -getWidth() / 2, -getHeight() / 2);
            g2.setColor(oldColor);
        }
    };


    public RotatingPaint() {

        // Inits control panel
        angleButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e){
                angle = Math.toRadians(Integer.parseInt(angleField.getText()));
                Rectangle oldBounds = littleWhitePanel.getBounds();
                Rectangle newBounds = getBoundsOfRotatedRectangle(oldBounds);
                littleWhitePanel.setBounds(newBounds);
                mainPanel.repaint();
            }
        });
        controlPanel.add(angleField);
        controlPanel.add(angleButton);

        // Inits main panel
        mainPanel.setPreferredSize(new Dimension(400, 300));
        mainPanel.setLayout(null);
        littleWhitePanel.setBounds(160, 100, 80, 20);
        littleWhitePanel.setBackground(Color.WHITE);
        mainPanel.add(littleWhitePanel);

        // Inits frame
        frame.setLayout(new BorderLayout());
        frame.add(controlPanel, BorderLayout.NORTH);
        frame.add(mainPanel, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        RotatingPaint app = new RotatingPaint();
    }

    /**
     * Applies the rotate transformation to a Point.
     * @param point the point to be rotated
     */
    private void rotatePoint(Point point) {
        Point centroid = new Point((int) littleWhitePanel.getBounds().getCenterX(), (int) littleWhitePanel.getBounds().getCenterY());
        int x = (int) Math.rint(centroid.x
                + (point.x - centroid.x) * Math.cos(angle)
                - (point.y - centroid.y) * Math.sin(angle));
        int y = (int) Math.rint(centroid.y
                + (point.x - centroid.x) * Math.sin(angle)
                + (point.y - centroid.y) * Math.cos(angle));
        point.x = x;
        point.y = y;
    }

    /**
     * @param rectangle the rectangle to be rotated
     * @return the bounding rectangle of the rotated rectangle
     */
    private Rectangle getBoundsOfRotatedRectangle(Rectangle rectangle) {

        // Getting each corner
        List<Point> corners = new ArrayList<Point>();
        Point topLeftCorner = rectangle.getLocation();
        corners.add(topLeftCorner);
        Point topRightCorner = new Point(topLeftCorner);
        topRightCorner.x += rectangle.width;
        corners.add(topRightCorner);
        Point bottomLeftCorner = new Point(topLeftCorner);
        bottomLeftCorner.y += rectangle.height;
        corners.add(bottomLeftCorner);
        Point bottomRightCorner = new Point(bottomLeftCorner);
        bottomRightCorner.x += rectangle.width;
        corners.add(bottomRightCorner);

        // Transforming each corner
        for (Point corner : corners) {
            rotatePoint(corner);
        }

        // Getting the min/max x and the min/max y
        int minX = corners.get(0).x;
        int minY = corners.get(0).y;
        int maxX = corners.get(0).x;
        int maxY = corners.get(0).y;
        for (int i = 1; i < corners.size(); i++) {
            minX = Math.min(minX, corners.get(i).x);
            minY = Math.min(minY, corners.get(i).y);
            maxX = Math.max(maxX, corners.get(i).x);
            maxY = Math.max(maxY, corners.get(i).y);
        }

        return new Rectangle(minX, minY, maxX - minX, maxY - minY);
    }
}
我设法重置了白色小面板的边界,但无法正确旋转文本。很难准确地描述什么不起作用。请执行该代码并自行检查

谢谢。

找到了。帮助了我。我更新了paintComponentGraphics gr方法,如下所示:

    @Override
    public void paintComponent(Graphics gr) {
        super.paintComponent(gr);
        Graphics2D g2 = (Graphics2D) gr;
        if (angle != 0) {
            // Moving to centroid
            g2.translate(getWidth()/2, getHeight()/2);
            g2.rotate(angle);
            // Moving back but using the string's dimensions
            // instead of the bounds (which have been changed)
            g2.translate(-stringWidth/2, -stringHeight/2);
        }
        g2.drawString("Hello World", 2, 12);
        if (angle != 0) {
            // Revert the transformation matrix back to its initial state
            g2.translate(stringWidth/2, stringHeight/2);
            g2.rotate(-angle);
            g2.translate(-getWidth()/2, -getHeight()/2);
        }
    }
关键在于执行以下调用:

translate(x, y);
rotate(theta);
translate(-x, -y);

但在我的情况下,我不想翻译回与原文完全相同的数量。我必须使用字符串的维度。

为此,我将使用3个连接的仿射变换实例。1将中心移动到原点。2旋转3将中心移动到原始位置。感谢您的评论@AndrewThompson。但是我调用g2.rotateangle、getWidth/2、getHeight/2;,不是已经在做什么了吗@AndrewThompson:或者,此变体将所有内容连接到一个实例中。@AndrewThompson:另请参见@Marcdeverdehan:是否要围绕字符串的中心旋转?