本文實例講述了Java編程實現的模擬行星運動。分享給大家供大家參考,具體如下:
期待了很久的Java語言程序設計也拉下了帷幕,在幾個月的時間里基本掌握了java的簡單用法,學習了java的主要基礎知識,面向對象思想,多線程並發控制,swing界面設計,動畫製作等,最後結課了也打算製作一個課程設計能夠盡可能多的涵蓋所學知識,將其進行串聯,因此考慮實現了一個簡單的模擬行星運動的小軟件,主要思路如下:
利用動畫實現行星運動的模擬,主面板裡有一個中心行星,同時繪製了橢圓軌道,有一顆運動的行星圍繞著中心行星運動。同時右下角設置的有四個按鈕,即“Start”、“Pause”、“accelerate”和“decelerate”分別可以使行星運動、暫停、加速、減速。
一、類的設計:
Star繼承自JPanel。 Star類是行星的基類,所有運動的行星都是繼承自Star類。內部draw()方法主要繪製了一個實心圓形,目的是在每次繪製時,可以保證中心行星始終顯示。 paintComponent()方法重寫了JPanel的繪製方法,目的是保證繼承自Star類的Stars類的實例對象可以繪製出自己的行星。如下:
package Star;import java.awt.Color;import java.awt.Graphics;import javax.swing.JPanel;public class Star extends JPanel{ /** * 基本的行星類*/ private static final long serialVersionUID = 1L; int x,y; int width,height; public Star() { width = 10; height = 10; } public Star(int x, int y){ this.x = x; this.y = y; width = 10; height = 10; } public void draw(Graphics g){ g.setColor(Color.blue); g.fillOval(x, y, width, height); } protected void paintComponent(Graphics g){ super.paintComponent(g); g.fillOval(x, y, width, height); }}Stars類繼承自Star類,是對Star類的進一步細化,表示運動的行星。 Stars類中的alfa表示運動行星的運動起始角度,speed表示運動速度,可對其進行修改。 Long,Short分別表示橢圓軌蹟的長軸與短軸。 center表示其實例化對象的中心行星。 paintComponent()函數重寫了paintComponent(),內部引用了父類的draw()函數,並且根據Long,,Short繪製了橢圓軌道,Long、Short由實例化對象調用構造方法來決定。 move()函數描述了x,y的變化方程,即圍繞著橢圓軌道變化,同時規定了alfa的變化方式。 start()函數表示線程開始,pause()函數表示線程暫停,accelerate()函數表示對行星的加速操作,decelerate()函數表示對行星減速的操作。
Pthread類目的是控制線程,即通過對Pthread類的實例化可以控制行星的開始運動,暫停運動,加速,減速。 Pthread類繼承自Thread類,且包含於Starts類中,因而,PThread類不能被定義為共有類。 PThread類提供了run()方法,不斷調用repaint()方法,對畫面進行重新繪製。 setsuspend()方法利用改變boolean變量對線程進行暫停操作(調用notifyall()方法)。因為Pthread類是Starts的內部類,所以之後Starts類中將生成一個PThread類的對象,並且利用該對象,對線程進行操作。
設計如下:
package Star;import java.awt.Color;import java.awt.Graphics;public class Stars extends Star{ /** * 運動的行星*/ private static final long serialVersionUID = 1L; double alfa ; double speed ; Star center; int Long ; //長軸int Short;//短軸public Stars(int Px,int Py,Star center){ super(Px,Py); this.center = center; Long = (Px - center.x)*2; Short = (Py - center.y)*2; this.setOpaque(true);// move(); alfa = 0; speed = 0.001; } protected void paintComponent(Graphics g){ super.paintComponent(g); center.draw(g);//畫出中心點move(); g.setColor(Color.GREEN); g.drawOval(center.x-Long/2, center.y-Short/2, Long, Short); } public void move(){ x = center.x + (int)(Long/2*Math.cos(alfa)); y = center.y + (int)(Short/2*Math.sin(alfa)); //沿橢圓軌跡運行alfa += speed; //角度不斷變化} class PThread extends Thread{ //重畫線程類private boolean suspend = true; private String control = ""; public void run(){ while(true){ synchronized (control) { if(suspend){ //move(); repaint(); } } } } public void setsuspend(boolean s){ //設置線程暫停方法if (!suspend) { synchronized (control) { control.notifyAll(); } } this.suspend = s; } } public PThread pt = new PThread(); public void start(){ pt.setsuspend(true); pt.start(); } public void pause(){ pt.setsuspend(false); } public void accelerate(){ //加速的方法if(speed > 0){ //角度每次加速0.0002 speed += 0.0002; } else speed = 0.001; } public void decelerate(){ //減速的方法if(speed > 0){ speed -= 0.0002; //角度每次減速0.0002 } //若減速到0,則不能繼續減速,另速度為0,停止運動else speed = 0; }}StarFrame類是本程序的啟動面板,通過實例化該類,生成主程序界面,並且將行星部件,按鈕,標籤添加進面板。內部的getPanel()方法對兩個按鈕進行了設置,並且返回一個JPanel(將四個按鈕添加進該JPanel中)。 getLabel()方法返回一個文字描述的JLabel。 Center對像是Star類的實例化,p1是Stars類的實例化,分別表示中心行星與環繞行星。 jb1,jb2,jb3,jb4分別是行星的啟動,暫停,加速,減速的控制按鈕。 image表示界面背景圖,LayeredPanel是界面的層次面板,方便背景圖的設置。 jp,jl是設置背景圖的部件。設計如下:
package Star;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Font;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.ImageIcon;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JLayeredPane;import javax.swing.JPanel;public class StarFrame extends JFrame{ /** *行星模擬啟動面板*/ private static final long serialVersionUID = 1L; Star center = new Star(300,200);//定義中心行星Stars p1 = new Stars(300+230,200+130,center);//環繞中心的行星Stars p2 = new Stars(300+230+20,200+130+20,p1); JButton jb1 = new JButton("start"); JButton jb2 = new JButton("pause"); JButton jb3 = new JButton("accelerate"); JButton jb4 = new JButton("decelerate"); ImageIcon image=new ImageIcon("timg.jpg");//背景圖,利用相對路徑定義JLayeredPane layeredPane; //定義一個層次面板,用於放置背景圖片JPanel jp; JLabel jl; public StarFrame(){ //為p1設置位置,與大小p1.setBounds(40,40,600,400);// p2.setBounds(40,40,600,400); //定義背景圖,將背景圖放於JLabel中,將JLabel放於JPanel中layeredPane = new JLayeredPane(); jp = new JPanel(); jp.setBounds(0,0,image.getIconWidth(),image.getIconHeight()); jl=new JLabel(image); jp.add(jl); //將jp放到最底層。 layeredPane.add(jp,JLayeredPane.DEFAULT_LAYER); //將jb放到高一層的地方layeredPane.add(p1,JLayeredPane.MODAL_LAYER);// layeredPane.add(p2,JLayeredPane.MODAL_LAYER); layeredPane.add(getPanel(),JLayeredPane.MODAL_LAYER); layeredPane.add(getLabel(),JLayeredPane.MODAL_LAYER); //分別為jb1、jb2、jb3、jb4設置相關動作jb1.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub p1.start(); } } ); jb2.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub p1.pause(); } }); jb3.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub p1.accelerate(); } }); jb4.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub p1.decelerate(); } }); this.setLayeredPane(layeredPane); this.setTitle("Star"); this.setBounds(100,100,1000, 600); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setVisible(true); } private JPanel getPanel(){ //返回定義的四個按鈕JPanel jp = new JPanel(); jp.add(jb1); jp.add(jb2); jp.add(jb3); jp.add(jb4); jp.setBounds(750,450,200,70); return jp; } private JPanel getLabel(){ //返回文字描述JLabel jl = new JLabel("行星模擬"); jl.setForeground(Color.RED);//設置字體顏色jl.setFont(new Font("Dialog",0,20));//設置字體JPanel jp = new JPanel(); jp.add(jl,BorderLayout.CENTER); jp.setBounds(800,0,150,40); return jp; } public static void main(String[] args) { @SuppressWarnings("unused") StarFrame f = new StarFrame(); }}運行效果:
二、對象:
因為java是面向對象的語言,當然不能像c語言一樣,僅僅靠函數實現,課設裡豈能沒有對象?
主要對象:
對象center,即中心行星
對象p1,即環繞行星
對象pt,即負責控制線程的對象
對象f,即程序啟動面板
三、對象之間的關係(交互)
p1與center的關係:Star類是行星的基類,繼承自JPanel,其內部定義了基本的半徑與坐標,其實例化對象center即是運動行星的中心行星。而繼承自Star的Stars類表示運動行星,是其進一步的細化,因此其實例化對象p1表示運動的行星1,且圍繞著center運動,同時center作為參數傳遞給p1的構造方法,完成二者交互。對象p1與center便是這樣的關係。實例化對象center後,便會在指定坐標下繪製實心圓形,center對象的x,y坐標不會變化。而對象p1在實現繪製實心圓形的基礎上,又根據center的坐標繪製了指定長軸,短軸的橢圓軌道,同時其內部實現了Thread類,不中斷的執行線程。相互的繼承關係,使得center和p1可以互不干擾的繪製圖形,值得一提的是,在Stras類中的paintComponent()方法中,仍需要調用center對象的draw()方法,因為線程開始時會調用repaint()方法,如果不實現center的draw()方法,那麼最終結果將不會顯示中心行星。
pt與p1的關係:PThread類繼承自Thread類,定義了run()方法,通過其實例化對象p1,可以調用start()方法啟動線程,而PThread類在Starts類內部,因而通過p1內的方法可以控制線程,即控制其速度,加速減速,控制其運行與否。
f與各對象的關係:StarFrame繼承自JFrame,其實例化對象f將各對象添加進繪畫布里,製作了界面,並控制了每個部件的大小、位置,是程序運行的關鍵。
四、面向對象的理解:
萬物皆對象,有些同學問我到底什麼才是對象,我回答說有new的都是對象,對象便是類的實例化,本程序中,可以通過對Stars類進行實例化從而創造出無數多個行星(理論上是的),但是內部函數的實現有些問題難以解決,主要便在paintComponent()方法的重寫上,再次創建對像後,便會再次重寫該方法,於是會出現不可避免的問題,也是無法解決的一個遺憾!
更多java相關內容感興趣的讀者可查看本站專題:《Java面向對象程序設計入門與進階教程》、《Java數據結構與算法教程》、《Java操作DOM節點技巧總結》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設計有所幫助。