如何在围绕画布中心的圆圈中绘制一个矩形?

时间:2016-11-13 07:54:30

标签: java animation

代码用于绘制一个矩形,该矩形围绕画布中心移动一次。我目前的代码是

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;
import javax.swing.Timer;
import javax.swing.JComponent;
import javax.swing.JFrame;

public class Q3_Circular extends JComponent {

protected int degree = 0;
protected double xStart;
protected double yStart;
protected Timer timer;


public Q3_Circular() {
    timer = new Timer(1000, new TimerCallback()); //creates new times that refreshes every 100 ms, and called the TimerCallback class
    timer.start();
}

protected class TimerCallback implements ActionListener {

    public void actionPerformed(ActionEvent e) {

        if (degree < (2 * Math.PI)){
            xStart = getWidth()/2 * Math.cos(degree+1);
            yStart = getHeight()/2 * Math.sin(degree+1);
            degree+= 1;
            repaint();
        }
        else {
            degree += 0;
            repaint();
        }

    }
}


public static void main(String[] args) {
    JFrame frame = new JFrame("AnimatedSquare");
    Q3_Circular canvas = new Q3_Circular();
    frame.add(canvas);
    frame.setSize(300, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);       
    frame.setVisible(true);
}   

public void paintComponent(Graphics g){
    xStart = (double)(getWidth())/2.0 * Math.cos(degree);
    yStart = (double)(getHeight())/2.0 * Math.sin(degree);

    Graphics2D g2 = (Graphics2D) g;
    g2.draw(new Rectangle2D.Double(xStart,yStart, 25,25));
    repaint();
}
}

此代码似乎在点(0,0)周围非常快速地绘制矩形。我不确定代码在哪里出错。

1 个答案:

答案 0 :(得分:1)

您的代码令人困惑。这是我创建的GUI。

Animated Square

创建Swing GUI时,请使用模型/视图/控制器模式。创建GUI模型和GUI视图,以及一个或多个控制器来修改模型并重新绘制视图。

以下是我对您的代码所做的更改。

  1. 我创建了一个DrawingRectangle类来保存有关绘图矩形的信息。这个类是一个带有getter和setter的普通旧Java对象。这个类是GUI模型。

  2. 除了调用SwingUtilities invokeLater方法之外,我将所有内容都移出main方法。 invokeLater方法在Event Dispatch thread上创建和使用Swing组件。 Oracle和我坚持认为所有Swing应用程序都是从Event Dispatch线程开始的。

  3. 我在Q3_Circular类的构造函数中创建绘图矩形。通常,您创建GUI模型,然后创建GUI视图。

  4. 我将run方法中的JFrame代码重新排列为正确的顺序。我删除了setSize方法并将其替换为pack方法。我们不关心JFrame有多大。我们关心绘图板的大小。

  5. 我从JPanel创建了一个绘图面板。在这里,我们设置绘图面板的首选大小。我们扩展了一个JPanel,因此我们可以覆盖paintComponent方法。

  6. paintComponent方法除了绘制绘图矩形外什么都不做。除了绘画之外,没有任何计算或任何东西在paintComponent方法中完成。我添加了对super paintComponent方法的调用,以在绘制绘图矩形之前维护Swing绘制链并清除绘图面板。我使用x和y坐标作为矩形的中心而不是左上角来绘制矩形。这是我在绘图代码中进行的一次转换。

  7. 我从Runnable创建了一个绘图动画。如果需要,您可以使用Swing Timer。我发现创建自己的动画代码更容易。这是GUI控制器。这是我们进行计算,更新模型和重绘绘图面板的地方。在重绘方法中,我使用SwingUtilities invokeLater方法在Event Dispatch线程上进行绘制。我这样做是因为动画线程是一个单独的线程。

  8. 这是代码。我将所有类放在一起,这样我就可以更轻松地粘贴代码了。您应该将类​​分成不同的文件。

    package com.ggl.testing;
    
    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.geom.Rectangle2D;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class Q3_Circular implements Runnable {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Q3_Circular());
        }
    
        private static final int DRAWING_WIDTH = 300;
        private static final int DRAWING_HEIGHT = DRAWING_WIDTH;
    
        private DrawingRectangle drawingRectangle;
    
        public Q3_Circular() {
            int center = DRAWING_WIDTH / 2;
            Rectangle2D rectangle = new Rectangle2D.Double(center, center, 32D, 32D);
            drawingRectangle = new DrawingRectangle(Color.RED, rectangle);
        }
    
        @Override
        public void run() {
            JFrame frame = new JFrame("Animated Square");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            DrawingPanel drawingPanel = new DrawingPanel(DRAWING_WIDTH,
                    DRAWING_HEIGHT, drawingRectangle);
            frame.add(drawingPanel);
    
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
    
            new Thread(new DrawingAnimation(drawingPanel, drawingRectangle))
                    .start();
        }
    
        public class DrawingPanel extends JPanel {
    
            private static final long serialVersionUID = 8226587438110549806L;
    
            private DrawingRectangle drawingRectangle;
    
            public DrawingPanel(int width, int height,
                    DrawingRectangle drawingRectangle) {
                this.setPreferredSize(new Dimension(width, height));
                this.drawingRectangle = drawingRectangle;
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
    
                g.setColor(drawingRectangle.getColor());
    
                Rectangle2D rectangle = drawingRectangle.getRectangle();
                int x = (int) Math.round(rectangle.getX());
                int y = (int) Math.round(rectangle.getY());
                int width = (int) Math.round(rectangle.getWidth());
                int height = (int) Math.round(rectangle.getHeight());
                g.fillRect(x - width / 2, y - height / 2, width, height);
            }
    
        }
    
        public class DrawingAnimation implements Runnable {
    
            private DrawingPanel drawingPanel;
    
            private DrawingRectangle drawingRectangle;
    
            public DrawingAnimation(DrawingPanel drawingPanel,
                    DrawingRectangle drawingRectangle) {
                this.drawingPanel = drawingPanel;
                this.drawingRectangle = drawingRectangle;
            }
    
            @Override
            public void run() {
                int xCenter = drawingPanel.getWidth() / 2;
                int yCenter = drawingPanel.getHeight() / 2;
                double radius = drawingPanel.getWidth() / 3;
    
                for (int degree = 0; degree < 360; degree++) {
                    double radians = Math.toRadians((double) degree);
                    double x = radius * Math.cos(radians) + xCenter;
                    double y = radius * Math.sin(radians) + yCenter;
                    drawingRectangle.setRectangleOrigin(x, y);
                    repaint();
                    sleep(100L);
                }
            }
    
            private void sleep(long interval) {
                try {
                    Thread.sleep(interval);
                } catch (InterruptedException e) {
    
                }
            }
    
            private void repaint() {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        drawingPanel.repaint();
                    }
                });
            }
        }
    
        public class DrawingRectangle {
    
            private final Color color;
    
            private Rectangle2D rectangle;
    
            public DrawingRectangle(Color color, Rectangle2D rectangle) {
                this.color = color;
                this.rectangle = rectangle;
            }
    
            public void setRectangleOrigin(double x, double y) {
                rectangle
                        .setRect(x, y, rectangle.getWidth(), rectangle.getHeight());
            }
    
            public Color getColor() {
                return color;
            }
    
            public Rectangle2D getRectangle() {
                return rectangle;
            }
    
        }
    
    }