动画不适用于Java图形

动画不适用于Java图形,java,animation,graphics,timer,actionlistener,Java,Animation,Graphics,Timer,Actionlistener,在用Java完成一个图形程序后,我正试图用定时器制作降雨的动画。现在我正在用一个大的蓝色矩形测试我的代码,这样我就可以看到它的去向,但是动画对我来说不起作用。我对Java图形非常陌生,所以我可能会犯一些我不清楚的错误 当我尝试重新绘制正方形以移动时,绘制函数称为“全屏幕闪烁”,这可能是因为我使用递归函数绘制分形树,但我不确定。有没有办法让我画的所有东西都不被重新粉刷,就在雨中重新粉刷?如有任何指导或提示,将不胜感激 import java.awt.*; import javax.swing.*;

在用Java完成一个图形程序后,我正试图用定时器制作降雨的动画。现在我正在用一个大的蓝色矩形测试我的代码,这样我就可以看到它的去向,但是动画对我来说不起作用。我对Java图形非常陌生,所以我可能会犯一些我不清楚的错误

当我尝试重新绘制正方形以移动时,绘制函数称为“全屏幕闪烁”,这可能是因为我使用递归函数绘制分形树,但我不确定。有没有办法让我画的所有东西都不被重新粉刷,就在雨中重新粉刷?如有任何指导或提示,将不胜感激

import java.awt.*;
import javax.swing.*;
import java.lang.Math;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class FractalTree extends JFrame {
    private int frameWidth = 1440;
    private int frameHeight = 850;
    private int rainX = 0;
    private int rainY = 0;

public FractalTree() 
{
    setBounds(1000, 1000, frameWidth, frameHeight ); //graphics window size
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    ActionListener listener = new TimerListener();
    final int DELAY = 1500;
    Timer t = new Timer(DELAY, listener);
    t.start();
    setResizable(false);

}

public void setRain(int newRainX, int newRainY)
{
    rainX = newRainX;
    rainY = newRainY;
}

public void setSkyGround(Graphics g)
{
   Color sky = new Color(180, 225, 255);
   g.setColor(sky);
   g.fillRect(0, 0, frameWidth, 550);

   Color sun = new Color(225, 225, 150);
   g.setColor(sun);

   g.fillOval(1380, -40, 100, 100);

   g.drawLine(frameWidth, 0, 1350, 550);
   g.drawLine(frameWidth, 0, 1450, 550);
   g.drawLine(1350, 550, 1450, 550);

   int xpoints[] = {frameWidth, 1450, 1350};
   int ypoints[] = {0, 550, 550};
   int npoints = 3;
   g.fillPolygon(xpoints, ypoints, npoints);

   g.drawLine(frameWidth, 0, 1080, 550);
   g.drawLine(frameWidth, 0, 880, 550);
   g.drawLine(880, 550, 1080, 550);

   int xpoints2[] = {frameWidth, 1080, 880};
   int ypoints2[] = {0, 550, 550};
   int npoints2 = 3;
   g.fillPolygon(xpoints2, ypoints2, npoints2);

   g.drawLine(frameWidth, 0, 480, 550);
   g.drawLine(frameWidth, 0, 280, 550);
   g.drawLine(480, 550, 280, 550);

   int xpoints3[] = {frameWidth, 480, 280};
   int ypoints3[] = {0, 550, 550};
   int npoints3 = 3;
   g.fillPolygon(xpoints3, ypoints3, npoints3);

   g.drawLine(frameWidth, 0, 0, 430);
   g.drawLine(frameWidth, 0, 0, 300);
   g.drawLine(0, 430, 0, 300);

   int xpoints4[] = {frameWidth, 0, 0};
   int ypoints4[] = {0, 430, 300};
   int npoints4 = 3;
   g.fillPolygon(xpoints4, ypoints4, npoints4);

   g.drawLine(frameWidth, 0, 0, 100);
   g.drawLine(frameWidth, 0, 0, 0);
   g.drawLine(0, 100, 0, 0);

   int xpoints5[] = {frameWidth, 0, 0};
   int ypoints5[] = {0, 0, 100};
   int npoints5 = 3;
   g.fillPolygon(xpoints5, ypoints5, npoints5);

   Color grassBackground = new Color(150, 255, 170);
   g.setColor(grassBackground);
   g.fillRect(0, 550, frameWidth, frameHeight);

}

public void drawTree(Graphics g, int x1, int y1, double angle, int depth, int red, int green, int blue) 
{
    if (depth == 0)
    { 
        Color doodle = new Color(red, green, blue);
        g.setColor(doodle);
        g.fillOval(x1, y1, 10, 10);  
    }
    else
    {
        Graphics2D g2 = (Graphics2D) g;
        g2.setStroke(new BasicStroke(depth));

        Color brown = new Color(100, 25, 0);
        g.setColor(brown);
        int x2 = x1 + (int) (Math.cos(Math.toRadians(angle)) * depth * 10);
        int y2 = y1 + (int) (Math.sin(Math.toRadians(angle)) * depth * 10);

        g.drawLine(x1, y1, x2, y2);

        drawTree(g, x2, y2, angle - 40, depth - 1, red, green, blue);
        drawTree(g, x2, y2, angle + 20, depth - 1, red, green, blue);
    }
}
public void realFlowers(Graphics g, int x, int y, int lenWid, int petals)
{
    //calculates the increment
    double inc = (2*Math.PI/petals);
    g.setColor(Color.YELLOW);
    //draws petals
    for(int i = 0; i < petals; i++){
        //keeps spacing consistent depandng on number of petals
        double value = i * inc;
        //draws petals with calculated spacing relative to number of petals
        g.fillOval((int)((lenWid)*Math.cos(value)+x-lenWid/4),(int)((lenWid)*Math.sin(value)+y-lenWid/4), lenWid + lenWid/2, lenWid + lenWid/2);
    }
    //draws middle flower bud;
    g.setColor(Color.ORANGE);
    g.fillOval(x - lenWid/4, y - lenWid/4, lenWid + lenWid/2 , lenWid + lenWid/2);
}

public void drawGrass(Graphics g, int width, int height, int interval, int red, int green, int blue)
{
    height = frameHeight - height;
    Color grass = new Color(red, green, blue);

    for(int i = 0; i < width; i= i + interval)
    {
        for(int j = frameHeight; j > height; j = j - interval)
        {
            g.setColor(grass);
            g.fillRect(i, j, 3, 5);
        }
    }
}

public void rainDrops(Graphics g, int x, int y, int w, int h)
{
    setRain(x, y);
    Color rain = new Color(0, 76, 153);
    g.setColor(rain);
    g.fillRect(x, y, w, h);
}

public void moveRainBy(int dx, int dy)
{
    rainX = rainX + dx;
    rainY = rainY + dy;
    repaint();
}

class TimerListener implements ActionListener
{
    public void actionPerformed(ActionEvent event)
    {
    moveRainBy(1, 1);
    }
}
public void paint(Graphics g) {

   setSkyGround(g);

   drawGrass(g, 1440, 315, 5, 0, 255, 0);
   drawGrass(g, 1430, 310, 10, 0, 204, 0);

   drawTree(g, 1085, 730, -90, 10, 255, 102, 102);
   drawTree(g, 250, 600, -90, 8, 255, 255, 255);
   drawTree(g, 1110, 740, -90, 4, 255, 102, 102);
   drawTree(g, 1060, 745, -90, 2, 255, 102, 102);

   realFlowers(g, 700,700, 8, 8);

   rainDrops(g, 200, 200, 30, 30);

}



public static void main(String[] args) {

    new FractalTree().setVisible(true);

}
}

当我尝试重新绘制正方形以移动时,绘制功能被称为“整个屏幕闪烁”

这是因为您已经覆盖了顶层容器JFrame的绘制,它不是双缓冲的

作为一般建议,您应该基于JPanel的核心功能,并覆盖它的paintComponent方法。查看和了解更多详细信息

您可能还想了解更多细节,了解为什么不建议直接从JFrame扩展并尝试对其进行绘制

有没有办法让我画的所有东西都不被重新粉刷,就在雨中重新粉刷

绘制是破坏性的,即每次调用paint/paintComponent时,都需要从头开始重新绘制组件的整个状态

您可以使用缓冲技术,使用BuffereImage之类的东西来绘制状态,并简单地让绘制方法绘制图像,但这取决于您想要的解决方案的复杂程度。如果你使用缓冲技术,我会考虑哪些元素是静态的,哪些元素是动态的。将这些静态元素绘制到缓冲区,然后在调用绘制时,在缓冲区顶部绘制动态元素