动画不起作用 Java 图形



在用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);
}

}

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

这是因为您已经覆盖了paint不是双缓冲的顶级容器(JFrame)。

作为一般建议,您应该围绕JPanel的核心功能,并覆盖它paintComponent方法。 查看在 AWT 和 Swing 中执行自定义绘画和绘画以获取更多详细信息

您可能还想看看如何获得屏幕的精确中间,即使重新调整大小和如何在中间设置?以获取更多详细信息,为什么不建议直接从JFrame扩展并尝试绘制到它。

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

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

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

最新更新