【问题标题】:Understanding Graphics 2D and rotate, drawRect methods了解图形 2D 和旋转、drawRect 方法
【发布时间】:2013-10-27 12:17:27
【问题描述】:

我试图了解如何使用 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 是旋转点。我也明白旋转方法中的 theta 是旋转角度。

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

我的问题是:

1) drawRect 方法中的 x 和 y 是什么(以及在 JPanel 位置方面),我如何根据我的情况解决它们? (我以为它是正方形的左上角,但如果我将 P2 拖到左上角会很混乱)

2) 我如何计算 P1 和 P2 的 theta?

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

【问题讨论】:

    标签: java swing rotation


    【解决方案1】:

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

    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) 计算旋转画布的角度,使第二点与x轴成45度角,以第一点为原点。

    3) 制作第一点原点。

    4) 旋转画布,使第二点与 x 轴成 45 度角,第一点为原点。这将使正方形的两侧落在轴上,另外两侧与轴平行,因此您可以使用图形的绘制方法来绘制矩形/正方形。

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

    6) 将画布向反方向旋转,使其与旋转前一样。

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

    完成!

    【讨论】:

    • 这是一件优雅的作品。我将尽职尽责地研究它。伟大的工作美拉曼!
    • :) 您必须将原点设置为锚点,旋转画布,使第二个点与 x 轴成 45 角,原点位于锚点。
    • 然后使用距离公式和毕达哥拉斯理论,计算正方形的边。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多