java线程的应用——窗体中会动的小球

此案例来源于书本是我对书中程序的改建与说明:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

import java.awt.*;
import java.lang.reflect.Field;
import javax.swing.JLabel;
/**展示面板*/
@SuppressWarnings("serial")
public class BallFrame extends JFrame {
    private JPanel Pane ;// 背景面板
    private Ball ball = null;// 窗体提供一个小球

测试方法:
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                BallFrame thisClass = new BallFrame();
                thisClass
                        .setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                thisClass.setVisible(true);
            }
        });
    }
    
    /**
     * 构造方法
     */
    public BallFrame() {
        super();
        initialize();// 初始程序界面
    }
    
    /**
     * 初始化程序界面
     */
    private void initialize() {
        this.setSize(512, 384);// 设置窗体大小
        this.setResizable(false);// 禁止调整窗体大小
        this.setContentPane(getJContentPane());// 添加内容面板
        // 设置窗体标题文本
        this.setTitle("窗体中的乒乓球----鼠标左键添加,右键减少");
    }
    
    /**
     * 背景面板
     * 
     * @return javax.swing.JPanel
     */
    private JPanel getJContentPane() {
        if (Pane == null) {
            ball = new Ball();// 创建第一个小球
            // 设置小球位置与大小
            ball.setBounds(new Rectangle(121, 67, 20, 20));
            // 创建背景面板
           Pane = new BGPanel();
            // 背景面板使用null布局
            Pane.setLayout(null);
            Pane.add(ball, null);// 添加第一个小球到背景面板
            // 为背景面板添加鼠标事件监听器
           Pane.addMouseListener(new MouseAdapter() {
                public void mousePressed(MouseEvent e) {
                    // 获取面板中控件的数量
                    int count = Pane.getComponentCount();
                    // 如果是单击鼠标左键,则添加小球
                    if (e.getButton() == MouseEvent.BUTTON1) {
                        if (count <= 20) {// 限制小球数量为20
                            Ball ball = new Ball();// 创建新的小球对象
                            Point point = e.getPoint();// 获取鼠标当前位置
                            ball.setLocation(point);// 设置小球为鼠标位置
                           Pane.add(ball);// 添加小球到面板
                        } else {// 否则
                            // 提示小球太多
                            JOptionPane.showMessageDialog(null,
                                    "球太多啦");
                        }
                    } else {// 如果单击鼠标右键
                        if (count < 1) {// 如果面板中没有控件
                            // 对话框提示信息
                            JOptionPane.showMessageDialog(null,
                                    "没有球啦");
                            return;
                        }
                        // 移除面板中的第一个控件
                       Pane.remove(0);
                        // 重新绘制面板
                        Pane.repaint();
                    }
                }
            });
        }
        return Pane;
    }
}

小球一个内部类:

class Ball extends JLabel implements Runnable {
    private int r = 10;// 小球半径
    private int width = r * 2;// 球宽度
    private int height = r * 2;// 球高度
    private Color ballColor = Color.BLACK;// 默认颜色
    
    /**
     * 构造方法
     */
    public Ball() {
        // 初始化大小
        setSize(new Dimension(width, height));
        setPreferredSize(new Dimension(width, height));
        // 反射获取Color类的所有成员变量数组
        Field[] fields = Color.class.getFields();
        // 随机生成数组下标索引
        int index = (int) (Math.random() * fields.length);
        try {
            // 获取指定下标索引的成员变量
            Object object = fields[index].get(null);
            // 判断是否Color类的实例对象
            if (object instanceof Color) {
                // 改变默认颜色
                ballColor = (Color) object;
            }
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        // 启动小球跳跃线程
        new Thread(this).start();
    }
    
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(ballColor);// 设置默认颜色
        g.fillOval(0, 0, width, height);// 绘制球体
    }
    
    @Override
    public void run() {
        // 获取父容器对象
        Container parent = getParent();
        Point myPoint = getLocation();// 获取初始位置
        while (true) {// 循环读取父容器对象
            if (parent == null) {
                try {
                    Thread.sleep(50);// 线程休眠
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                myPoint = getLocation();// 获取初始位置
                parent = getParent();
            } else {// 如果已经获取到父容器
                break;// 跳出循环
            }
        }
        int sx = myPoint.x;// X坐标
        int sy = myPoint.y;// y坐标
        int step = (int) (Math.random() * 10) % 3 + 1;// 移动步进
        int dx = (Math.random() * 100) >= 50 ? step : -step;// 水平步进值
        step = (int) (Math.random() * 10) % 3 + 1;// 移动步进
        int dy = (Math.random() * 100) >= 50 ? step : -step;// 垂直步进值
        // 随机移动速度
        int stime = (int) (Math.random() * 80 + 10);
        while (parent.isVisible()) {
            int parentWidth = parent.getWidth();// 容器宽度
            int parentHeight = parent.getHeight();// 容器高度
            setLocation(sx, sy);
            try {
                Thread.sleep(stime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            sx = sx + dx * 5;// 水平坐标偏移5个像素
            sy = sy + dy * 5;// 垂直坐标偏移5个像素
            // 检测垂直边界
            if (sy > parentHeight - height - 15 || sy - 20 < 0)
                dy = -dy;// 防止坐标超出垂直边界
            // 检测水平边界
            if (sx > parentWidth - width - 25 || sx - 20 < 0)
                dx = -dx;// 防止坐标超出水平边界
        }
    }
}

此程序运行无错后上传

如有错误我会尽快修改后上传

你可能感兴趣的:(案例开发)