我想根据旋转角度和相应面板的质心周围旋转paintComponent(Graphics g)
方法中绘制的内容。
这是我最初的想法:
用于设置角度的控制面板(文本字段+按钮)(以度为单位,从0到359)。主面板包含一个小白板。当用户点击“设置角度”按钮时,必须更新小白色面板(setBounds()
和repaint()
)。无论如何,小白板必须以其质心为中心。
这就是我想要的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);
}
}
我设法重置小白色面板的边界,但我无法正确旋转文本。很难描述什么不能正常工作。请执行该代码并自行检查。
谢谢。
答案 0 :(得分:0)
实测值。 This example帮助了我。我更新了paintComponent(Graphics 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);
}
}
关键是Graphics2D#rotate()
执行以下调用:
translate(x, y);
rotate(theta);
translate(-x, -y);
但在我的情况下,我不想翻译与原始翻译完全相同的金额。我不得不使用字符串的尺寸。