这个程序总共创建了4个大类:
下面是程序运行的GIF动态图
通过键盘空格来控制泡泡的移动或者停止,通过鼠标点击来使得泡泡填充颜色,再次点击填充消失
1.AlgoFrame 继承JFrame类
import org.omg.PortableInterceptor.DISCARDING;
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Ellipse2D;
public class AlgoFrame extends JFrame {
private int canvasWidth;
private int canvasHeight;
public AlgoFrame(String title,int canvasWidth,int canvasHeight){
super(title);
this.canvasWidth = canvasWidth;
this.canvasHeight = canvasHeight;
AlgoCanvas canvas = new AlgoCanvas();
canvas.setPreferredSize(new Dimension(canvasWidth,canvasHeight));
setContentPane(canvas);
pack();
setSize(canvasWidth,canvasHeight);
setResizable(false);
setVisible(true);
}
public int getcanvasWidth(){return canvasWidth;}
public int getCanvasHeight(){return canvasHeight;}
private Circle[] circles;
public void render(Circle[] circles){
this.circles = circles;
repaint();
}
private class AlgoCanvas extends JPanel{
//zhi支持双缓存
public AlgoCanvas(){
super(true);
}
@Override//覆盖函数
public void paintComponent(Graphics g){
super.paintComponent(g);
//g.drawOval(50,50,300,300);
Graphics2D g2d = (Graphics2D)g;
//抗锯齿
RenderingHints hints = new RenderingHints(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.addRenderingHints(hints);
//具体绘制
AlgoVisHelper.setStrokeWidth(g2d,1);
AlgoVisHelper.setColor(g2d,Color.red);
for(Circle circle:circles)
if(!circle.isFilled)
AlgoVisHelper.strokeCircle(g2d,circle.x,circle.y,circle.getR());
else
AlgoVisHelper.fillCircle(g2d,circle.x,circle.y,circle.getR());
}
}
@Override
public Dimension getPreferredSize(){
return new Dimension(canvasWidth,canvasHeight);
}
}
2.AlgoVisHelper算法绘制辅助函数类,即一个工具类
import java.awt.*;
import java.awt.geom.Ellipse2D;
public class AlgoVisHelper {
private AlgoVisHelper(){}
public static void setStrokeWidth(Graphics2D g2d ,int w ){
int strokeWidth = w;
g2d.setStroke(new BasicStroke(strokeWidth,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND));
}
public static void strokeCircle(Graphics2D g2d,int x,int y,int r){
Ellipse2D circle = new Ellipse2D.Double(x-r,y-r,2*r,2*r);
g2d.draw(circle);
}
public static void fillCircle(Graphics2D g2d,int x,int y,int r){
Ellipse2D circle = new Ellipse2D.Double(x-r,y-r,2*r,2*r);
g2d.fill(circle);
}
public static void setColor(Graphics2D g2d,Color color ){
g2d.setColor(color);
}
public static void pause(int t){
try{
Thread.sleep(t);
}
catch (InterruptedException e ){
System.out.println("Error in sleeping.");
}
}
}
3.Circle类
添加相应的成员变量,(位置速度和半径)
import java.awt.*;
public class Circle{
public int x,y;
private int r;
public int vx,vy;
public boolean isFilled = false;
public Circle(int x,int y,int r,int vx, int vy){
this.x = x;
this.y = y;
this.r = r;
this.vx = vx;
this.vy = vy;
}
public int getR(){return r;}
public void move(int minx,int miny,int maxx,int maxy){
x +=vx;
y +=vy;
checkCollision(minx,miny,maxx,maxy);
}
private void checkCollision(int minx,int miny, int maxx,int maxy){
if(x-r < minx){x = r;vx = -vx;}
if(x+r >= maxx){x = maxx-r;vx = -vx;}
if(y-r < miny){y = r;vy = -vy;}
if(y+r >= maxy){y = maxy-r;vy = -vy;}
}
public boolean contain(Point p){
return (x-p.x)*(x-p.x)+(y-p.y)*(y-p.y)<=r*r;
}
}
4.AlgoVisualizer相当于一个控制类
同时控制数据以及视图(即circle 和 frame)
import java.awt.*;
import java.awt.event.*;
import static javafx.scene.input.KeyCode.R;
public class AlgoVisualizer {
private Circle[] circles;
private AlgoFrame frame;
private boolean isAnimated = true;
public AlgoVisualizer(int sceneWidth,int sceneHight,int N){
circles = new Circle[N];
int R = 50;
for (int i =0;i<N;i++){
int x =(int)(Math.random()*(sceneWidth-2*R)+R) ;
int y =(int)(Math.random()*(sceneHight-2*R)+R) ;
int vx =(int)(Math.random()*(10)-5) ;
int vy = (int)(Math.random()*10)-5;
circles[i] = new Circle(x,y,R,vx,vy);
}
EventQueue.invokeLater(() -> {
frame = new AlgoFrame("Welcome",sceneWidth,sceneHight);
frame.addKeyListener(new AlgoKeyListener());
frame.addMouseListener(new AlgoMouseListener());
new Thread(()->{
run();
}).start();
});
}
private void run(){
while(true){
//绘制数据
frame.render(circles);
AlgoVisHelper.pause(20);
//geng更新数据
if(isAnimated)
for(Circle circle:circles)
circle.move(0,0,frame.getcanvasWidth(),frame.getCanvasHeight());
}
}
private class AlgoKeyListener extends KeyAdapter {
@Override
public void keyReleased(KeyEvent event){
if ((event.getKeyChar() == ' '));
isAnimated = !isAnimated;
}
}
private class AlgoMouseListener extends MouseAdapter{
@Override
public void mousePressed(MouseEvent event){
event.translatePoint(0, -26);
//System.out.println(event.getPoint());
for (Circle circle:circles)
if (circle.contain(event.getPoint()))
circle.isFilled = !circle.isFilled;
}
}
public static void main(String[] args){
int sceneWidth = 600;
int sceneHeight = 600;
int N = 10;
AlgoVisualizer visualizer = new AlgoVisualizer(sceneWidth,sceneHeight,N);
}
}
这就是键盘鼠标可控的泡泡撞击事件的基本原理:有想交流的大佬们可评论区留言!