java - 了解 Graphics 2D 和旋转、drawRect 方法

标签 java swing rotation

我想了解如何使用 Graphics 2D 类的 drawRect(int x, int y, int width, int height) 方法和 rotate(double theta, double x, double y) 方法。

我想要做的是在 JPanel 上绘制一个正方形并旋转它(所有这些都使用鼠标)。因此,此过程将是 - 单击 1(这将给出点 1 (P1) 的坐标 - 这是正方形的一个角),移动鼠标(鼠标位置给出点 2 (P2) 的坐标 - 这是正方形的对角),旋转正方形(同样,鼠标位置将给出点 2 的坐标)。单击 2(点 2 通过此单击更新,是正方形的最终静止位置)

我的理解和问题是:

我知道 P1.x 和 P1.y 是旋转方法中使用的值。 P1 是旋转点。我也明白rotate方法中的theta是旋转的角度。

我知道 drawRect 方法的宽度和高度应该等于一个正方形,但这是我开始感到困惑的地方。

我的问题是:

1) drawRect 方法中的 x 和 y 是什么(以及在 JPanel 位置方面的位置)以及如何根据我的情况计算出它们? (我以为是正方形的左上角,但是如果我把P2拖到左上角就乱了)

2) 如何从 P1 和 P2 计算出 theta?

(注意:这是什么好处,我正在使用 MouseAdapter 方法来处理点击和鼠标移动)

最佳答案

出于好奇,我做了这样的东西。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class RectanglePanel extends JPanel{
    private Point anchorPoint = null;
    private Point intermediatePoint = null;
    private Point finalPoint = null;

    public RectanglePanel(){
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me){
                if(anchorPoint == null){
                    // first click, set anchor point
                    anchorPoint = me.getPoint();
                }else if(finalPoint == null){
                    // second click, set final point
                    finalPoint = me.getPoint();
                }else{
                    // third click, reset clicks, anchor point, intermediate point and final point
                    anchorPoint = null;
                    finalPoint = null;
                    intermediatePoint = null;
                }
                repaint();
            }
        });
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent me){
                if(anchorPoint != null && finalPoint == null){
                    // mouse moved
                    // set intermediate point if anchor point is set and final point is not set yet
                    intermediatePoint = me.getPoint();
                    repaint();
                }
            }
        });
    }

    @Override
    protected void paintComponent(Graphics g){
        super.paintComponent(g);

        if(anchorPoint != null){
            Graphics2D g2d = (Graphics2D) g;
            g2d.setColor(Color.red);

            Point p = finalPoint != null ? finalPoint : intermediatePoint;

            if(p != null && !p.equals(anchorPoint)){
                // final point or intermediate point is set, and is not same as anchor point
                // draw square

                // calculate angle to rotate canvas
                double angle = -Math.toRadians(45) + Math.atan2(p.y - anchorPoint.y, p.x - anchorPoint.x);
                // width of square, calculated using distance formaula and pythagorus theorem
                // distance formula: distance = sqrt((x1-x2)^2 + (y1-y2)^2)
                // pythagorus for right angled triangle: c^2 = a^2 + b^2
                double width = Math.sqrt(((p.x - anchorPoint.x) * (p.x - anchorPoint.x) + (p.y - anchorPoint.y) * (p.y - anchorPoint.y)) / 2.0);
                // set origin to anchorpoint
                g2d.translate(anchorPoint.x, anchorPoint.y);
                // rotate canvas
                g2d.rotate(angle);

                Rectangle2D rectangle2D = new Rectangle2D.Double(0, 0, width, width);
                // draw square
                g2d.draw(rectangle2D);

                // rotate back canvas
                g2d.rotate(-angle);

                // reset back origin
                g2d.translate(-anchorPoint.x, -anchorPoint.y);
            }else{
                g2d.drawRect(anchorPoint.x, anchorPoint.y, 1, 1);
            }
        }
    }

    public static void main(String [] args){
        final JFrame frame = new JFrame("Rectangle Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(500, 400);
        frame.getContentPane().add(new RectanglePanel());
        SwingUtilities.invokeLater(new Runnable() {
           public void run() {
               frame.setVisible(true);
            }
        });
    }
}

你可以这样实现,来解决你的问题。让我知道这是否是您要找的东西?

步骤:

1) 计算正方形的宽度。你有点,代表正方形的对角。这两点之间的距离就是对角线的长度。因此,考虑两个点 (x1, y1)(x2, y2),使用距离公式,对角线的长度由下式给出:

diagonal_length * diagonal_length = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)

正方形和对角线的两条边可以组成直角三角形。正方形的边长相等,令正方形的边为side,然后使用毕达哥拉斯定理:

side * side + side * side = diagonal_length * diagonal_length

求解以上两个方程,

side  = Math.sqrt(((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) / 2.0);

2) 计算旋转 Canvas 的角度,以第一个点为原点,使第二个点与 x 轴成 45 度角。

3) 制作第一点原点。

4) 旋转 Canvas ,使第二点与 x 轴成 45 度角,第一点为原点。这样就可以使正方形的两条边落在坐标轴上,另外两条边与坐标轴平行,这样就可以使用图形的draw方法绘制矩形/正方形。

5) 从原点绘制边长如上计算的正方形。

6) 反向旋转 Canvas ,使其与旋转前一样。

7) 将原点重置为设置原点之前的原点。

完成!

关于java - 了解 Graphics 2D 和旋转、drawRect 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19617924/

相关文章:

java - 如何在android中解析JSON字符串数组

java - 使用多线程更新GUI

math - 平面的 3D 旋转

android - 为什么支持FragmentManager.saveFragmentInstanceState(selectedFragment)!! = 空

Java 8 流 - 增量收集/部分减少/间歇映射/...这甚至叫什么?

java - JSF RichFaces 和双 slider

java - 如何使用流在 Java 8 中按值范围分组

java - 为什么这个 GUI 程序运行时框架没有居中?

Java Swing - 添加带有约束的小部件时出现 NullPointerException

ios - 如何使每个 UIView 的底部与圆相切,以便它们从中心辐射?