简体   繁体   English

Java 图形 - 如何在绘制调用之间添加延迟以创建动画?

[英]Java graphics - how to add delay between paint calls to create animation?

I'm designing a simple fractal program in Java that will start by drawing a rectangle then recursively draw rectangles 1/4 the size at each corner.我正在用 Java 设计一个简单的分形程序,它首先绘制一个矩形,然后递归地绘制每个角的 1/4 大小的矩形。 This will repeat and span in all directions until the dimensions converge to 0.这将在所有方向上重复和跨越,直到维度收敛到 0。

I have the program and design completely functional as of now;到目前为止,我的程序和设计已经完全正常运行; however, I'm making additions that I am unsure of how to do.但是,我正在添加我不确定如何做的补充。 When I run the program, the fractal is shown already complete in the JFrame that pops up.当我运行程序时,分形在弹出的 JFrame 中显示已经完成。 What I want to do is have each rectangle appear individually with a short delay between each one being painted.我想要做的是让每个矩形单独出现,每个矩形之间都有很短的延迟。

I have a class for my main method which simply instantiates a GUI object and calls its run() method.我的 main 方法有一个类,它只是实例化一个 GUI 对象并调用它的 run() 方法。 For the most part, all the relevant code exists in these two files.大多数情况下,所有相关代码都存在于这两个文件中。

In the GUI class在 GUI 类中

public GUI()
 {
      Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
      fractal = new Fractal(this, screenSize.width, screenSize.height);

      this.setTitle("Fractals");
      this.setSize(screenSize.width, screenSize.height);
      this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      this.getContentPane().add(fractal);
      this.setFocusable(true);
      this.setVisible(true);
 }

 public void run()
 {
      fractal.repaint();
 }

In the Fractal class在分形类中

public Fractal(GUI gui, int width, int height)
 {
      this.gui = gui;
      this.screenWidth = width;
      this.screenHeight = height;
 }

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

      /* Calculate coordinates and dimensions */
      int x = 3 * this.screenWidth / 8;
      int y = 3 * this.screenHeight / 8;
      int width = this.screenWidth / 4;
      int height = this.screenHeight / 4;

      /* Draw the center rectangle */
      g.setColor(Color.BLACK);
      g.fillRect(x, y, width, height);

      /* Adjust dimensions for next rectangles */
      width /= 2;
      height /= 2;

      /* Draw rectangles at the corners */
      drawTopLeft(g, x - width, y - height, width, height);
      drawBottomLeft(g, x - width, y + (2 * height), width, height);
      drawTopRight(g, x + (2 * width), y - height, width, height);
      drawBottomRight(g, x + (2 * width), y + (2 * height), width, height);
 }

 public void drawTopLeft(Graphics g, int x, int y, int width, int height)
 {
      /* Ensure the boundaries lay within the screen */
      if(x > 0 && y > 0)
      {
           /* Draw itself */
           g.fillRect(x, y, width, height);

           /* Adjust dimensions for next rectangles */
           width /= 2;
           height /= 2;

           /* Draw rectangles at the corners */
           if(width > 0 && height > 0)
           {
                drawTopLeft(g, x - width, y - height, width, height);
                drawBottomLeft(g, x - width, y + (2 * height), width, height);
                drawTopRight(g, x + (2 * width), y - height, width, height);
           }
      }
 }

 public void drawBottomLeft(Graphics g, int x, int y, int width, int height)
 {
      /* Ensure the boundaries lay within the screen */
      if(x > 0 && y + height < screenHeight)
      {
           /* Draw itself */
           g.fillRect(x, y, width, height);

           /* Adjust dimensions for next rectangles */
           width /= 2;
           height /= 2;

           /* Draw rectangles at the corners */
           if(width > 0 && height > 0)
           {
                drawTopLeft(g, x - width, y - height, width, height);
                drawBottomLeft(g, x - width, y + (2 * height), width, height);
                drawBottomRight(g, x + (2 * width), y + (2 * height), width, height);
           }
      }
 }

 public void drawTopRight(Graphics g, int x, int y, int width, int height)
 {
      /* Ensure the boundaries lay within the screen */
      if(x + width < screenWidth && y > 0)
      {
           /* Draw itself */
           g.fillRect(x, y, width, height);

           /* Adjust dimensions for next rectangles */
           width /= 2;
           height /= 2;

           /* Draw rectangles at the corners */
           if(width > 0 && height > 0)
           {
                drawTopLeft(g, x - width, y - height, width, height);
                drawTopRight(g, x + (2 * width), y - height, width, height);
                drawBottomRight(g, x + (2 * width), y + (2 * height), width, height);
           }
      }
 }

 public void drawBottomRight(Graphics g, int x, int y, int width, int height)
 {
      /* Ensure the boundaries lay within the screen */
      if(x + width < screenWidth && y + height < screenHeight)
      {
           /* Draw itself */
           g.fillRect(x, y, width, height);

           /* Adjust dimensions for next rectangles */
           width /= 2;
           height /= 2;

           /* Draw rectangles at the corners */
           if(width > 0 && height > 0)
           {
                drawBottomLeft(g, x - width, y + (2 * height), width, height);
                drawTopRight(g, x + (2 * width), y - height, width, height);
                drawBottomRight(g, x + (2 * width), y + (2 * height), width, height);
           }
      }
 }

Here is what the output generates.这是输出生成的内容。

分形生成

You need to calculate each rectangle outside of the paintComponent method.您需要计算paintComponent 方法之外的每个矩形。 Each subsequent one should be stored in an array or list or some data structure.每个后续的都应存储在数组或列表或某种数据结构中。 Then call repaint and sleep for 1 second (but don't sleep in the paintComponent method).然后调用 repaint 并休眠 1 秒(但不要在paintComponent 方法中休眠)。

Your paintComponent method must then iterate thru the list of rectangles and paint each one.然后,您的paintComponent 方法必须遍历矩形列表并绘制每个矩形。 So each time repaint is called, your old ones and then your new one will be painted.因此,每次调用 repaint 时,都会先绘制旧的,然后再绘制新的。

Bottom line, do not do much processing in paintComponent or any other method that runs in the EDT or your application will become unresponsive or not work as desired.最重要的是,不要在 paintComponent 或在 EDT 中运行的任何其他方法中进行太多处理,否则您的应用程序将变得无响应或无法按预期工作。

One more thing.还有一件事。 Any drawing that you do in paintComponent will not be visible until you leave the method.在离开该方法之前,您在paintComponent 中所做的任何绘图都将不可见。

I didn't see you image earlier.我之前没有看到你的图片。 If you are going to be drawing curves or diagonal lines, then set the following in paintComponent before painting.如果要绘制曲线或对角线,请在绘制前在paintComponent 中设置以下内容。 It will smooth out the graphics.它将使图形平滑。

Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM