《看的见的算法》视频中写的Java动画模板,很容易理解,记个笔记:
Model:
public class Circle {
int x;
int y;
int r = 0;
int direction = 1;
public Circle(int x, int y) {
this.x = x;
this.y = y;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getR() {
return r;
}
public void changeSize(int min, int max) {
if(r<min || r>max) //初始化是让r在这个范围内
r = min;
r = r + direction;
if(r==max || r==min) {
direction = - direction;
}
}
}
View:
public class ViewFrame extends JFrame{
private int canvasWidth;
private int canvasHeight;
public ViewFrame(String title, int canvasWidth, int canvasHeight){
super(title);
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
Canvas canvas = new Canvas();
setContentPane(canvas);
pack();//frame可以随着JPanel自动伸缩
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
}
public int getCanvasWidth(){return canvasWidth;}
public int getCanvasHeight(){return canvasHeight;}
private Object data; //直接改变这里的类型,可以在后面避免进行类型转换
public void render(Object data){
this.data = data;
repaint();
}
private class Canvas extends JPanel{
public Canvas(){
// 双缓存
super(true);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
// 抗锯齿
RenderingHints hints = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
hints.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.addRenderingHints(hints);
// 将data在这里具体绘制,例如:
VisHelper.setColor(g2d, VisHelper.Red);
if(data!=null) {
Circle circle = (Circle) data;
VisHelper.drawCircle(g2d, circle.getX(), circle.getY(), circle.getR());
}
}
@Override //通过实现此方法让JPanel可以设置我们需要的大小
public Dimension getPreferredSize(){
return new Dimension(canvasWidth, canvasHeight);
}
}
}
Controller:
public class Visualizer {
private Object data; // 数据
private ViewFrame frame; // 视图
public Visualizer(int sceneWidth, int sceneHeight){
// 初始化数据,例如:
data = new Circle(sceneWidth/2, sceneHeight/2);
// 初始化视图
EventQueue.invokeLater(() -> {
frame = new ViewFrame("xxx's frame", sceneWidth, sceneHeight);
//添加事件
//frame.add*Listener(new *Listener());
new Thread(() -> { //因为EventQueue.invokeLater
run(); //不放在线程里可能会阻碍后续的绘画过程
}).start(); //除非运行代码可以很快结束
});
}
// 动画逻辑
private void run(){
//编写动画逻辑,例如:
while(true) {
Circle circle = (Circle)data;
frame.render(circle);
circle.changeSize(0,200);
VisHelper.pause(10);
}
}
// 事件监听器类
// private class *Listener extends *Adapter{ }
//启动代码
public static void main(String[] args) {
int sceneWidth = 500;
int sceneHeight = 500;
// 初始化visualizer
Visualizer visualizer = new Visualizer(sceneWidth, sceneHeight);
}
}
工具类:
//helper类
public class VisHelper {
private VisHelper(){}
//颜色
public static final Color Red = new Color(0xF44336);
public static final Color Pink = new Color(0xE91E63);
public static final Color Purple = new Color(0x9C27B0);
//等等颜色...
//绘制空心圆
public static void drawCircle(Graphics2D g, int x, int y, int r){
Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r);
g.draw(circle);
}
//绘制实心圆
public static void fillCircle(Graphics2D g, int x, int y, int r){
Ellipse2D circle = new Ellipse2D.Double(x-r, y-r, 2*r, 2*r);
g.fill(circle);
}
//设置颜色
public static void setColor(Graphics2D g, Color color){
g.setColor(color);
}
//设置线条宽度
public static void setStrokeWidth(Graphics2D g, int w){
int strokeWidth = w;
g.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));//参数使拐弯处圆润
}
//线程暂停
public static void pause(int t) {
try {
Thread.sleep(t);
}
catch (InterruptedException e) {
System.out.println("error");
}
}
//等等方法...
}
运行后,写在代码中小例子运行结果会是一个从小变大,在从大变小的空心圆