跟着王洋老师学编程 - 1.4 飞行的小球

发布时间 2023-12-13 12:10:01作者: Shannon_Zhang

一、我的思路

  1. 画一个窗体,并设定大小
  2. 准备一个画布,并将画布添加至窗体
  3. 在画布上用paint方法实现小球的运动 —— 用一个for循环,小球x轴不变,先画一个球,然后改变画笔颜色与背景色相同,在原位置上再画一个小球;改变小球Y轴坐标,改变画笔颜色,在新的位置重新画小球,循环直到Y轴坐标达到窗体最大值结束。

代码版本1 - 直线下落:

 1 import java.awt.Frame;
 2 import java.awt.Panel;
 3 import java.awt.Graphics;
 4 import java.awt.Color;
 5 public class DroppingBall{
 6     public static void main(String[] args){
 7         Frame w = new Frame();
 8         w.setSize(1366,768);
 9         
10         MyPanelB mpb = new MyPanelB();
11         w.add(mpb);
12         w.show();
13     }
14 }
15 
16 class MyPanelB extends Panel{
17     public void paint(Graphics g){
18         int x=30,y=30;
19         g.drawOval(x,y,10,10);
20         for(;y<768;y++){
21             g.setColor(Color.white);
22             g.drawOval(x,y,10,10);
23             y++;
24             g.setColor(Color.black);
25             g.drawOval(x,y,10,10);
26         }
27     }
28 }

编译及执行结果如下:

现象1 - 没有实现下落的动态效果,只显示一条直线。

思考1 - 是不是坐标变化的粒度太小,改为斜线呢。。?

代码版本2 - 斜线下落:

 1 import java.awt.Frame;
 2 import java.awt.Panel;
 3 import java.awt.Graphics;
 4 import java.awt.Color;
 5 public class DroppingBall{
 6     public static void main(String[] args){
 7         Frame w = new Frame();
 8         w.setSize(1366,768);
 9         
10         MyPanelB mpb = new MyPanelB();
11         w.add(mpb);
12         w.show();
13     }
14 }
15 
16 class MyPanelB extends Panel{
17     public void paint(Graphics g){
18         int x=5,y=5;
19         g.fillOval(x,y,10,10);
20         for(;x<1366;){
21             for(;y<768;y++){
22                 g.setColor(Color.white);
23                 g.fillOval(x,y,10,10);
24                 x++;
25                 y++;
26                 g.setColor(Color.black);
27                 g.fillOval(x,y,10,10);
28             }
29         }
30     }
31 }

编译及运行结果如下:

现象2 - 没有实现动态下落效果,只显示一条斜线。

思考2 - 小球没有按预想的在A位置出现、抹掉,在A+1位置重现、再抹掉……如果不用循环呢?

代码版本3 - 去掉循环。。:

 1 import java.awt.Frame;
 2 import java.awt.Panel;
 3 import java.awt.Graphics;
 4 import java.awt.Color;
 5 public class DroppingBall{
 6     public static void main(String[] args){
 7         Frame w = new Frame();
 8         w.setSize(1366,768);
 9         
10         MyPanelB mpb = new MyPanelB();
11         w.add(mpb);
12         w.show();
13     }
14 }
15 
16 class MyPanelB extends Panel{
17     public void paint(Graphics g){
18         int x=5,y=5;
19         g.fillOval(x,y,10,10);
20         g.setColor(Color.white);
21         g.fillOval(x,y,10,10);
22         x=30;
23         y=30;
24         g.setColor(Color.black);
25         g.fillOval(x,y,10,10);
26 
27         g.setColor(Color.white);
28         g.fillOval(x,y,10,10);
29         x=100;
30         y=100;
31         g.setColor(Color.black);
32         g.fillOval(x,y,10,10);
33     }
34 }

编译及运行结果如下: 

去掉循环之后,看不到线的轨迹了,说明旧位置的小球确实被“擦除”了,但看不到小球下落的效果;而加上循环,显示的却是小球的轨迹,看起来小球的旧位置并没有被“擦除”——

结论 - 不管循环是否存在,都没有实现小球动态下落的结果。。看起来如果能在原位置的小球“擦除”之后加入延时。。

二、老师的讲解

1、引入了线程,并线程与进程的区别

进程 - 一个独立运行的程序,比如一个正在运行的记事本、一个正在运行的浏览器;启动两次记事本,得到的也是两个线程。

线程 - 一个进程当中的单一顺序的控制流

https://m.runoob.com/java/java-multithreading.html

2、用线程实现小球下落效果的思路

代码版本1 - 线程固定用法

 1 import java.awt.*;
 2 public class DroppingBall{
 3     public static void main(String args[]){
 4         Frame w = new Frame();
 5         w.setSize(1366,768);
 6         
 7         MyPanelB mpb = new MyPanelB();
 8         w.add(mpb);
 9 
10         // 使用线程对象
11         Thread t = new Thread(mpb);
12         t.start();
13 
14         // w.show();
15         w.setVisible(true);
16     }
17 }
18 
19 class MyPanelB extends Panel implements Runnable{
20     int x=5,y=5;
21     public void paint(Graphics g){
22         g.fillOval(x,y,10,10);
23     }
24     public void run(){
25         while(true){
26             y++;
27             if(y>768){
28                 y=5;
29             }
30             try{
31                 Thread.sleep(1000);
32             }catch(Exception e){
33                 System.out.println(e);
34                 System.out.println(y);
35                 repaint();
36             }
37         }
38     }
39 }

编译并运行后,结果如下:

 小球一直在初始位置不动。。各种打印后,发现try里面的代码执行了,但repaint()方法一直未执行,各种搜索博客也没解决。最后,去了一趟厕所,沉思……try...catch... catch是异常处理,发生异常,才抛出或处理异常,没有异常……啊!

结论:repaint()写错位置。。。。

解决方案

 1 import java.awt.*;
 2 public class DroppingBall{
 3     public static void main(String args[]){
 4         Frame w = new Frame();
 5         w.setSize(1366,768);
 6         
 7         MyPanelB mpb = new MyPanelB();
 8         w.add(mpb);
 9 
10         // 使用线程对象
11         Thread t = new Thread(mpb);
12         t.start();
13 
14         w.show();
15     }
16 }
17 // 通过实现Runnable接口使用线程
18 class MyPanelB extends Panel implements Runnable{
19     int x=5,y=5;
20     public void paint(Graphics g){
21         g.fillOval(x,y,10,10);
22     }
23     public void run(){
24         while(true){
25             y++;
26             if(y>768){
27                 y=5;
28             }
29             try{
30                 Thread.sleep(1000);
31             }catch(Exception e){
32                 System.out.println(e);
33             }
34             repaint();
35         }
36     }
37 }

编译及运行结果如下:

看到小球每秒下移一次~~~~~O(∩_∩)O~~~~~

最后,加快下移速度,并把过时的 show()方法,改为 setVisible(true)方法

 1 import java.awt.*;
 2 public class DroppingBall{
 3     public static void main(String args[]){
 4         Frame w = new Frame();
 5         w.setSize(1366,768);
 6         
 7         MyPanelB mpb = new MyPanelB();
 8         w.add(mpb);
 9 
10         // 使用线程对象
11         Thread t = new Thread(mpb);
12         t.start();
13 
14         // w.show();
15         w.setVisible(true);
16     }
17 }
18 // 通过实现Runnable接口使用线程
19 class MyPanelB extends Panel implements Runnable{
20     int x=5,y=5;
21     public void paint(Graphics g){
22         g.fillOval(x,y,10,10);
23     }
24     public void run(){
25         while(true){
26             y++;
27             if(y>768){
28                 y=5;
29             }
30             try{
31                 Thread.sleep(100);
32             }catch(Exception e){
33                 System.out.println(e);
34             }
35             repaint();
36         }
37     }
38 }

小球实现了匀速下移!~