使用gui创建一个窗口:
public class TestApp {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame("Welcome");
frame.setSize(500, 500);
frame.setResizable(false);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
创建一个窗口和面板:
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;
//setSize(canvasWidth, canvasHeight);
AlgoCanvas canvas = new AlgoCanvas();
// canvas.setPreferredSize(new Dimension(canvasWidth,canvasHeight));
setContentPane(canvas);
pack();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setVisible(true);
// System.out.println(getContentPane().getBounds());
}
public AlgoFrame(String title){
this(title, 1024, 768);
}
private class AlgoCanvas extends JPanel{
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(50, 50, 300, 300);
}
@Override
public Dimension getPreferredSize(){
return new Dimension(canvasWidth, canvasHeight);
}
}
}
Graphics2D 进行画图操作:
private class AlgoCanvas extends JPanel {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// g.drawOval(50, 50, 300, 300);
Graphics2D g2d = (Graphics2D) g;
int strokeWidth = 5;
g2d.setStroke(new BasicStroke(strokeWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));//设置线条宽度
g2d.setColor(Color.RED);//设置颜色,直到下次颜色改变
Ellipse2D circle = new Ellipse2D.Double(50, 50, 300, 300);
g2d.draw(circle);
g2d.setColor(Color.BLUE);
Ellipse2D circle2 = new Ellipse2D.Double(50, 50, 300, 300);
g2d.fill(circle2);
}
通过指定圆心、半径来绘制圆形:
public class AlgoVisHelper {
private AlgoVisHelper() {
}
public static void strokeCircle(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));
}
}
private class AlgoCanvas extends JPanel {
@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.setColor(g2d, Color.BLUE);
AlgoVisHelper.fillCircle(g2d, width/2,height/2,200);
AlgoVisHelper.setStrokeWidth(g2d,5);
AlgoVisHelper.setColor(g2d, Color.RED);
AlgoVisHelper.strokeCircle(g2d, width/2,height/2,200);
}
}
public AlgoCanvas(){
// 双缓存
super(true);
}
圆圈类:
public class Circle {
public int x;
public int y;
private int r;
public int vx;
public int vy;
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 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);
// 具体绘制
AlgoVisHelper.setStrokeWidth(g2d,1);
AlgoVisHelper.setColor(g2d, Color.RED);
for(Circle circle: circles)
AlgoVisHelper.strokeCircle(g2d, circle.x, circle.y, circle.getR());
}
mvc在算法中的体现:
public class AlgoVisualizer {
private Circle[] circles; // 数据
private AlgoFrame frame; // 视图
public AlgoVisualizer(int sceneWidth, int sceneHeight, 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() * (sceneHeight - 2 * R)) + R;
int vx = (int) (Math.random() * 11) - 5;
int vy = (int) (Math.random() * 11) - 5;
circles[i] = new Circle(x, y, R, vx, vy);
}
// 初始化视图
EventQueue.invokeLater(() -> {
frame = new AlgoFrame("Welcome", sceneWidth, sceneHeight);
new Thread(() -> {
run();
}).start();
});
}
// 动画逻辑
private void run() {
while (true) {
// 绘制数据
frame.render(circles);
AlgoVisHelper.pause(20);
// 更新数据
for (Circle circle : circles)
circle.move(0, 0, frame.getWidth(), frame.getHeight());
}
}
}
public static void main(String[] args) {
int sceneWidth = 800;
int sceneHeight = 800;
// init data
int N = 10;
AlgoVisualizer algoVisualizer = new AlgoVisualizer(sceneWidth, sceneHeight, N);
}
gui中的键盘事件:
public class AlgoVisualizer {
private Circle[] circles;
private AlgoFrame frame;
private boolean isAnimated = true;
public AlgoVisualizer(int sceneWidth, int sceneHeight, 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() * (sceneHeight - 2 * R)) + R;
int vx = (int) (Math.random() * 11) - 5;
int vy = (int) (Math.random() * 11) - 5;
circles[i] = new Circle(x, y, R, vx, vy);
}
// 初始化视图
EventQueue.invokeLater(() -> {
frame = new AlgoFrame("Welcome", sceneWidth, sceneHeight);
frame.addKeyListener(new AlgoKeyListener());
new Thread(() -> {
run();
}).start();
});
}
public void run() {
while (true) {
// 绘制数据
frame.render(circles);
AlgoVisHelper.pause(20);
// 更新数据
if (isAnimated)
for (Circle circle : circles)
circle.move(0, 0, frame.getWidth(), frame.getHeight());
}
}
private class AlgoKeyListener extends KeyAdapter {
@Override
public void keyReleased(KeyEvent event) {
if (event.getKeyChar() == ' ')
isAnimated = !isAnimated;
}
}
public static void main(String[] args) {
int sceneWidth = 800;
int sceneHeight = 800;
int N = 10;
AlgoVisualizer vis = new AlgoVisualizer(sceneWidth, sceneHeight, N);
}
}
gui中鼠标事件:
public class AlgoVisualizer {
private Circle[] circles;
private AlgoFrame frame;
private boolean isAnimated = true;
public AlgoVisualizer(int sceneWidth, int sceneHeight, 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()*(sceneHeight-2*R)) + R;
int vx = (int)(Math.random()*11) - 5;
int vy = (int)(Math.random()*11) - 5;
circles[i] = new Circle(x, y, R, vx, vy);
}
// 初始化视图
EventQueue.invokeLater(() -> {
frame = new AlgoFrame("Welcome", sceneWidth, sceneHeight);
frame.addKeyListener(new AlgoKeyListener());
frame.addMouseListener(new AlgoMouseListener());
new Thread(() -> {
run();
}).start();
});
}
// 动画逻辑
private void run(){
while(true){
// 绘制数据
frame.render(circles);
AlgoVisHelper.pause(20);
// 更新数据
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){
//System.out.println(event.getPoint());
event.translatePoint(0,
-(frame.getBounds().height - frame.getCanvasHeight()));
for(Circle circle : circles)
if(circle.contain(event.getPoint()))
circle.isFilled = !circle.isFilled;
}
}
public static void main(String[] args) {
int sceneWidth = 800;
int sceneHeight = 800;
int N = 10;
AlgoVisualizer visualizer = new AlgoVisualizer(sceneWidth, sceneHeight, N);
}
}