您可以使用我的AnimationPanel
课程并在其中进行绘图。该技术基于主动渲染。
代码:
// AnimationPanel.java
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public abstract class AnimationPanel extends JPanel implements Runnable
{
private static final long serialVersionUID = 6892533030374996243L;
private static final int NO_DELAYS_PER_YIELD = 16;
private static final int MAX_FRAME_SKIPS = 5;
private static long fps = 30; // Frames Per Second.
private static long period = 1000000L * (long) 1000.0 / fps;
protected final int WIDTH;
protected final int HEIGHT;
private Thread animator;
private volatile boolean running = false;
private volatile boolean isWindowPaused = false;
private Graphics dbg;
private Image dbImage = null;
public AnimationPanel(int width, int height)
{
WIDTH = width;
HEIGHT = height;
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setFocusable(true);
requestFocus();
}
public void addNotify()
{
super.addNotify();
startAnimation();
}
void startAnimation()
{
if (animator == null || !running)
{
animator = new Thread(this);
animator.start();
}
}
public void run()
{
long beforeTime, afterTime, timeDiff, sleepTime;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
beforeTime = System.nanoTime();
running = true;
while (running)
{
requestFocus();
animationUpdate();
animationRender();
paintScreen();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleepTime = (period - timeDiff) - overSleepTime;
if (sleepTime > 0)
{
try
{
Thread.sleep(sleepTime / 1000000L);
}
catch (InterruptedException ignored)
{
}
overSleepTime = (System.nanoTime() - afterTime - sleepTime);
}
else
{
excess -= sleepTime;
overSleepTime = 0L;
if (++noDelays >= NO_DELAYS_PER_YIELD)
{
Thread.yield();
noDelays = 0;
}
}
beforeTime = System.nanoTime();
int skips = 0;
while ((excess > period) && (skips < MAX_FRAME_SKIPS))
{
excess -= period;
animationUpdate();
skips++;
}
}
stopAnimation();
System.exit(0);
}
void stopAnimation()
{
running = false;
}
private void animationUpdate()
{
if (!isWindowPaused)
{
update();
}
}
public abstract void update();
private void animationRender()
{
if (dbImage == null)
{
dbImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
if (dbImage == null)
{
System.out.println("Image is null.");
return;
}
else
{
dbg = dbImage.getGraphics();
}
}
draw(dbg);
}
public abstract void draw(Graphics graphics);
private void paintScreen()
{
Graphics g;
try
{
g = this.getGraphics();
if ((g != null) && (dbImage != null))
{
g.drawImage(dbImage, 0, 0, null);
}
Toolkit.getDefaultToolkit().sync();
if (g != null)
{
g.dispose();
}
}
catch (Exception e)
{
System.out.println("Graphics context error : " + e);
}
}
public void setWindowPaused(boolean isPaused)
{
isWindowPaused = isPaused;
}
}
如何使用:
AnimationPanel
是一个JPanel
。将此类复制粘贴到您的项目中。
创建另一个类,并使其扩展AnimationPanel
。
覆盖其中声明为抽象 的update()
和draw()
方法。AnimationPanel
在update()
方法内部,您可以更改在您的自定义类中声明的变量的值。这些变量将是动画所需的变量,并且在帧与帧之间不断变化。
在draw()
方法内部,使用您在自定义类中定义的变量进行所有自定义绘制。
setWindowPaused()
如果您愿意,也可以使用方法暂停动画。
示范:
// DemonstrationPanel.java
import java.awt.*;
public class DemonstrationPanel extends AnimationPanel
{
private int red, green, blue;
private int a, b, c, d;
public DemonstrationPanel(int WIDTH, int HEIGHT)
{
super(WIDTH, HEIGHT);
red = 100;
green = blue = 5;
a = 2;
b = 500;
c = 200;
d = 5;
}
@Override
public void update()
{
red += 5;
red %= 255;
blue += 1;
blue %= 255;
green += 10;
green %= 255;
a += 20;
a %= HEIGHT;
b += 1;
b %= WIDTH;
c += 15;
c %= HEIGHT;
d += 20;
d %= WIDTH;
}
@Override
public void draw(Graphics graphics)
{
// Uncomment the below two statements to just see
// one line per frame of animation:
// graphics.setColor(BACKGROUND_COLOR);
// graphics.fillRect(0, 0, WIDTH, HEIGHT);
graphics.setColor(new Color(red, green, blue));
graphics.drawLine(b, c, d, a);
}
}
这是Demo
课程:
// Demo.java
import javax.swing.*;
import java.awt.*;
public class Demo
{
public Demo()
{
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DemonstrationPanel(800, 600));
frame.setBackground(Color.BLACK);
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
new Demo();
}
});
}
}
你可以调整类中的值fps
来AnimationPanel
改变动画的速度。