JAVA——多线程(碰撞的球)

版权声明:DY113 https://blog.csdn.net/Atishoo_13/article/details/83214004

多线程(碰撞的球)


1.要求

本实例运用多线程控制球的运动,通过窗口中的滑条,对球的大小和颜色进行选择后,随机从窗口左右两方择一进入,小球在遇到障碍或边界后会折回。

2.原理

  • 多线程是为了使得多个线程并行地工作以完成多项任务,以提高系统的效率。线程是在同一时间需要完成多项任务的时候被实现的。
  • 碰撞的小球运用多线程实现,球的运动速度随着时间的变动可能加快,这也是体现多线程的好处之一。从左右两侧出现的球是运用两个线程分别控制的。当碰到面板的边缘时则折回。

3.语法

  • BallFrame类继承JFramea类实现ActionListener与ChangeListeneri接口。实现ActionListener接口必须实现actionPerformed()方法,实现 ChangeListenert接口必须实现state Changed()方法。在BallFrame类的构造方法中创建面板并设置面板的大小、位置、背景颜色;创建预览面板并设置预览面板的大小、位置与背景颜色:创建文本框作为状态栏并设置其大小、位置,初始不可编辑;创建红绿蓝和球大小的四个标签,并设置标签的位置,创建红绿蓝以及球大小四个滑块并设置滑块的大小、位置、填充滑块、绘制勾号标记、设置主要的勾号标记大小、设置次要的勾号标记大小、设置主要刻度的数字标记以及添加监听器。创建注入球按钮,当单击该按钮时触发事件在面板中导入两个运动的球。创建窗体容器并设置其布局为空,这样可以在窗体容器中随意摆放组件,再将相关的组件诉加到窗体容器中,设置窗体容器的位置大小以及可视化,当关闭窗体时调用系统的exit(0)方法安全退出程序。
  • BallFrame类的actionPerformed()方法根据红绿蓝滑块中指定的颜色获取当前球的颜色。根据面板、球的大小以及球的颜色创建 RightBall和LeftBall对象,并启动线程。这样球就可以注入到面板中运动了。
  • BallFrame类的stateChanged()方法获得预览面板中的画笔,在预览面板的中心画一个圆,并设置该图形的颜色为白色和填充外接指定矩形框的圆。根据设置球大小的滑块值设置圆的半径。重新设置图形的颜色和填充外接指定矩形框的圆, Graphics类的dispose()方法将所画的圆显示出来。
  • LeftBall类和 RightBall类继承 Thread类扩展run()方法,其构造方法获得球的面板、大小以及颜色。run()方法根据面板的 getGraphics()方法获得球的图形,并根据获得的球的大小计算画球时横纵坐标的最大坐标。运用条件始终为真进行循环,球毎移动一步,将上一步画的球的颜色设置为白色来将球擦掉,并获得新的球的横纵坐标。如果球运动到面板的边缘则球转向。设置左球与右球毎隔30毫秒移动一次。

4.代码

主程序:

public class rw34 {
	//操作运用线程实现碰撞的球的类
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new BallFrame();//实例化对象
	}

}

对窗口界面进行设计:

class BallFrame extends JFrame implements ActionListener,ChangeListener{
	private static final long serialVersionUID=1L;
	JPanel panel;//画板
	JPanel preview;//预览画板
	JSlider red;//红色滑块
	JSlider blue;//蓝色滑块
	JSlider green;//绿色滑块
	JSlider JS_SIZE;//滑块的大小
	int x=45,y=45;//方位
	int BALL_SIZE=30;//球的大小
	public BallFrame() {
		//构造方法进行初始化
		super("碰撞的球");
		panel=new JPanel();//创建面板
		panel.setBounds(20, 0, 450, 200);//设置面板的位置及大小
		panel.setBackground(Color.WHITE);//面板背景色为白色
		preview=new JPanel(); //创建预览球的面板
		preview.setBounds(350,220,120,120);
		preview.setBackground(Color.WHITE);//设置状态栏
		JTextField status=new JTextField("请选择球的颜色、大小然后单击按钮");
		status.setBounds(1,404,492,20);//设置状态栏的位置以及大小
		status.setEditable(false);//初始不能编辑
		JLabel redLabel=new JLabel("红");//创建红色标签
		redLabel.setBounds(20,215,30,20);//设置红色标签的位置以及大小
		JLabel greenLabel=new JLabel("绿");//创建绿色标签
		greenLabel.setBounds(20,260,30,20);//设置绿色标签的位置以及大小
		JLabel blueLabel=new JLabel("蓝");//创建蓝色标签
		blueLabel.setBounds(20,305,30,20);//设置蓝色标签的位置以及大小
		JLabel sizeLabel=new JLabel("大小");//创建大小标签
		sizeLabel.setBounds(20,350,30,20);//设置大小标签的位置以及大小
		red=new JSlider(SwingConstants.HORIZONTAL,0,255,127);//创建红色滑块
		red.setBounds(50, 210, 250, 45);//设置滑块的位置以及大小
		red.putClientProperty("JSlider.isFilled",Boolean.TRUE);//填充滑块
		red.setPaintTicks(true);//绘制勾号标记
		red.setMajorTickSpacing(50);//主要的勾号标记大小
		red.setMinorTickSpacing(25);//次要的勾号标记大小
		red.setPaintLabels(true);//显示主要刻度的数字标记
		red.addChangeListener(this);//添加监听者
		blue=new JSlider(SwingConstants.HORIZONTAL,0,255,127);//创建蓝色滑块
		blue.setBounds(50, 300, 250, 45);//设置滑块的位置以及大小
		blue.putClientProperty("JSlider.isFilled",Boolean.TRUE);//填充滑块
		blue.setPaintTicks(true);//绘制勾号标记
		blue.setMajorTickSpacing(50);//主要的勾号标记大小
		blue.setMinorTickSpacing(25);//次要的勾号标记大小
		blue.setPaintLabels(true);//显示主要刻度的数字标记
		blue.addChangeListener(this);//添加监听者
		green=new JSlider(SwingConstants.HORIZONTAL,0,255,127);//创建绿色滑块
		green.setBounds(50, 255, 250, 45);//设置滑块的位置以及大小
		green.putClientProperty("JSlider.isFilled",Boolean.TRUE);//填充滑块
		green.setPaintTicks(true);//绘制勾号标记
		green.setMajorTickSpacing(50);//主要的勾号标记大小
		green.setMinorTickSpacing(25);//次要的勾号标记大小
		green.setPaintLabels(true);//显示主要刻度的数字标记
		green.addChangeListener(this);//添加监听者
		//创建球大小的滑块
		JS_SIZE=new JSlider(SwingConstants.HORIZONTAL,10,50,30);//创建大小滑块
		JS_SIZE.setBounds(50,345,250,45);//设置滑块的位置以及大小
		JS_SIZE.putClientProperty("JSlider.isFilled", Boolean.TRUE);//填充滑块
		JS_SIZE.setPaintTicks(true);//绘制勾号标记
		JS_SIZE.setMajorTickSpacing(50);//主要的勾号标记大小
		JS_SIZE.setMinorTickSpacing(25);//次要的勾号标记大小
		JS_SIZE.setPaintLabels(true);//显示主要刻度的数字标记
		JS_SIZE.addChangeListener(this);//添加监听者
		JButton jb=new JButton("注入球");//创建球按钮单击
		jb.setBounds(350,360,120,30);//设置按钮的位置以及大小
		jb.addActionListener(this);
		Container c=this.getContentPane();//将所有对象添加到窗体
		c.setLayout(null);  //布局置空(不使用布局)
		c.add(panel);
		c.add(preview);
		c.add(redLabel);
		c.add(blueLabel);
		c.add(greenLabel);
		c.add(sizeLabel);
		c.add(red);
		c.add(green);
		c.add(blue);
		c.add(JS_SIZE);
		c.add(jb);
		c.add(status);
		this.setBounds(100,50,500,450);//设置窗体的位置和大小
		this.setResizable(false);
		this.setVisible(true);//可视
		this.addWindowListener(new WindowAdapter(){//对窗口添加监听事件
			public void windowClosing(WindowEvent e) {//当窗口关闭时
				System.exit(0);//安全退出
			}
		});
	}
	public void actionPerformed(ActionEvent e) {//实现ActionListener接口的方法
		Color ball_color=new Color(red.getValue(),green.getValue(),blue.getValue());//获取当前球的颜色
		Random random=new Random();
		int z = random.nextInt(2);//产生一个随机数,使球随机从两边进入,随机数取值范围为1,0
		if(z==1) {
		RightBall r=new RightBall(panel,JS_SIZE.getValue(),ball_color);//实例化右边的球对象
		r.start();//启动线程
		}else {
		LeftBall ball=new LeftBall(panel,JS_SIZE.getValue(),ball_color);//实例化左边的球对象
		ball.start();//启动线程
		}
	}
	public void stateChanged(ChangeEvent e) {//实现ChangeListener接口的方法
		Graphics g=preview.getGraphics();//获得preview画笔并在预览面板中心画个圈
		g.setColor(Color.WHITE);//图形为白色
		g.fillOval(x, y, BALL_SIZE, BALL_SIZE);//填充外接指定矩形框的圆
		x=60-JS_SIZE.getValue()/2;
		y=60-JS_SIZE.getValue()/2;
		BALL_SIZE=JS_SIZE.getValue();
		g.setColor(new Color(red.getValue(),green.getValue(),blue.getValue()));
		g.fillOval(x, y, BALL_SIZE, BALL_SIZE);//填充外接指定矩形框的圆
		g.dispose();//显示
	}
}

继承Thread类实现从窗口左面出现的球,窗口右边的球与此原理相同:

class LeftBall extends Thread{//继承Thread类实现从窗口左面出现的球
	JPanel LEFTPANEL;//从窗口左面出现的球的面板
	int BALL_SIZE;//球的大小
	Color BALL_COLOR;//球的颜色
	public LeftBall(JPanel panel,int size,Color color) {//构造方法进行初始化
		this.LEFTPANEL=panel;//获得画板的句柄
		this.BALL_SIZE=size;//获得球的大小
		this.BALL_COLOR=color;//获得球的颜色
	}
	public void run() {  //继承Thread类实现的方法
		Graphics g= LEFTPANEL.getGraphics();//获得图形
		int x=0,y=0;
		int LEFT_X=450-BALL_SIZE;//计算画球时X轴的最大坐标
		int LEFT_Y=200-BALL_SIZE;//计算画球时Y轴的最大坐标
		int x_increase=5,y_increase=5;//球移动的增量
		while(true) {
			//循环移动球
			g.setColor(Color.WHITE);//将上一次画的球擦掉
			g.fillOval(x,y,BALL_SIZE, BALL_SIZE);//填充外接指定矩形框的圆
			g.setColor(BALL_COLOR);//设置球的颜色
			x=x+x_increase;//球每次X轴的位置
			y=y+y_increase;//球每次Y轴的位置
			g.fillOval(x,y,BALL_SIZE, BALL_SIZE);//填充外接指定矩形框的圆
			if(x<=0||x>=LEFT_X)//判断球是否到达了便捷,若到达了边界则转向
				x_increase=-x_increase;
			if(y<=0||y>=LEFT_Y)//判断球是否到达了便捷,若到达了边界则转向
				y_increase=-y_increase;
			try {
				Thread.sleep(30);//休眠一段时间
			}catch(Exception e) {
				//捕获异常
			}
		}
		
	}
}

获取完整代码可点击此处

5.结果

运行结果如下图所示:
在这里插入图片描述
窗口界面如下图所示:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Atishoo_13/article/details/83214004
今日推荐