1. 程式人生 > >JAVA——多執行緒(碰撞的球)

JAVA——多執行緒(碰撞的球)

多執行緒(碰撞的球)

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.結果

執行結果如下圖所示:
在這裡插入圖片描述
視窗介面如下圖所示:
在這裡插入圖片描述