Java編程實現(xiàn)的模擬行星運(yùn)動示例
本文實例講述了Java編程實現(xiàn)的模擬行星運(yùn)動。分享給大家供大家參考,具體如下:
期待了很久的Java語言程序設(shè)計也拉下了帷幕,在幾個月的時間里基本掌握了java的簡單用法,學(xué)習(xí)了java的主要基礎(chǔ)知識,面向?qū)ο笏枷耄嗑€程并發(fā)控制,swing界面設(shè)計,動畫制作等,最后結(jié)課了也打算制作一個課程設(shè)計能夠盡可能多的涵蓋所學(xué)知識,將其進(jìn)行串聯(lián),因此考慮實現(xiàn)了一個簡單的模擬行星運(yùn)動的小軟件,主要思路如下:
利用動畫實現(xiàn)行星運(yùn)動的模擬,主面板里有一個中心行星,同時繪制了橢圓軌道,有一顆運(yùn)動的行星圍繞著中心行星運(yùn)動。同時右下角設(shè)置的有四個按鈕,即“Start”、“Pause”、“accelerate”和“decelerate”分別可以使行星運(yùn)動、暫停、加速、減速。
一、類的設(shè)計:
Star繼承自JPanel。Star類是行星的基類,所有運(yùn)動的行星都是繼承自Star類。內(nèi)部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類的進(jìn)一步細(xì)化,表示運(yùn)動的行星。Stars類中的alfa表示運(yùn)動行星的運(yùn)動起始角度,speed表示運(yùn)動速度,可對其進(jìn)行修改。Long,Short分別表示橢圓軌跡的長軸與短軸。center表示其實例化對象的中心行星。paintComponent()函數(shù)重寫了paintComponent(),內(nèi)部引用了父類的draw()函數(shù),并且根據(jù)Long,,Short繪制了橢圓軌道,Long、Short由實例化對象調(diào)用構(gòu)造方法來決定。move()函數(shù)描述了x,y的變化方程,即圍繞著橢圓軌道變化,同時規(guī)定了alfa的變化方式。start()函數(shù)表示線程開始,pause()函數(shù)表示線程暫停,accelerate()函數(shù)表示對行星的加速操作,decelerate()函數(shù)表示對行星減速的操作。
Pthread類目的是控制線程,即通過對Pthread類的實例化可以控制行星的開始運(yùn)動,暫停運(yùn)動,加速,減速。Pthread類繼承自Thread類,且包含于Starts類中,因而,PThread類不能被定義為共有類。PThread類提供了run()方法,不斷調(diào)用repaint()方法,對畫面進(jìn)行重新繪制。setsuspend()方法利用改變boolean變量對線程進(jìn)行暫停操作(調(diào)用notifyall()方法)。因為Pthread類是Starts的內(nèi)部類,所以之后Starts類中將生成一個PThread類的對象,并且利用該對象,對線程進(jìn)行操作。
設(shè)計如下:
package Star;
import java.awt.Color;
import java.awt.Graphics;
public class Stars extends Star{
/**
* 運(yùn)動的行星
*/
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));
//沿橢圓軌跡運(yùn)行
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){
//設(shè)置線程暫停方法
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,則不能繼續(xù)減速,另速度為0,停止運(yùn)動
else speed = 0;
}
}
StarFrame類是本程序的啟動面板,通過實例化該類,生成主程序界面,并且將行星部件,按鈕,標(biāo)簽添加進(jìn)面板。內(nèi)部的getPanel()方法對兩個按鈕進(jìn)行了設(shè)置,并且返回一個JPanel(將四個按鈕添加進(jìn)該JPanel中)。getLabel()方法返回一個文字描述的JLabel。Center對象是Star類的實例化,p1是Stars類的實例化,分別表示中心行星與環(huán)繞行星。jb1,jb2,jb3,jb4分別是行星的啟動,暫停,加速,減速的控制按鈕。image表示界面背景圖,LayeredPanel是界面的層次面板,方便背景圖的設(shè)置。jp,jl是設(shè)置背景圖的部件。設(shè)計如下:
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);//環(huán)繞中心的行星
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設(shè)置位置,與大小
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設(shè)置相關(guān)動作
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);//設(shè)置字體顏色
jl.setFont(new Font("Dialog",0,20));//設(shè)置字體
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();
}
}
運(yùn)行效果:

二、對象:
因為java是面向?qū)ο蟮恼Z言,當(dāng)然不能像c語言一樣,僅僅靠函數(shù)實現(xiàn),課設(shè)里豈能沒有對象?
主要對象:
對象center,即中心行星
對象p1,即環(huán)繞行星
對象pt,即負(fù)責(zé)控制線程的對象
對象f,即程序啟動面板
三、對象之間的關(guān)系(交互)
p1與center的關(guān)系:Star類是行星的基類,繼承自JPanel,其內(nèi)部定義了基本的半徑與坐標(biāo),其實例化對象center即是運(yùn)動行星的中心行星。而繼承自Star的Stars類表示運(yùn)動行星,是其進(jìn)一步的細(xì)化,因此其實例化對象p1表示運(yùn)動的行星1,且圍繞著center運(yùn)動,同時center作為參數(shù)傳遞給p1的構(gòu)造方法,完成二者交互。對象p1與center便是這樣的關(guān)系。實例化對象center后,便會在指定坐標(biāo)下繪制實心圓形,center對象的x,y坐標(biāo)不會變化。而對象p1在實現(xiàn)繪制實心圓形的基礎(chǔ)上,又根據(jù)center的坐標(biāo)繪制了指定長軸,短軸的橢圓軌道,同時其內(nèi)部實現(xiàn)了Thread類,不中斷的執(zhí)行線程。相互的繼承關(guān)系,使得center和p1可以互不干擾的繪制圖形,值得一提的是,在Stras類中的paintComponent()方法中,仍需要調(diào)用center對象的draw()方法,因為線程開始時會調(diào)用repaint()方法,如果不實現(xiàn)center的draw()方法,那么最終結(jié)果將不會顯示中心行星。
pt與p1的關(guān)系:PThread類繼承自Thread類,定義了run()方法,通過其實例化對象p1,可以調(diào)用start()方法啟動線程,而PThread類在Starts類內(nèi)部,因而通過p1內(nèi)的方法可以控制線程,即控制其速度,加速減速,控制其運(yùn)行與否。
f與各對象的關(guān)系:StarFrame繼承自JFrame,其實例化對象f將各對象添加進(jìn)繪畫布里,制作了界面,并控制了每個部件的大小、位置,是程序運(yùn)行的關(guān)鍵。
四、面向?qū)ο蟮睦斫猓?/strong>
萬物皆對象,有些同學(xué)問我到底什么才是對象,我回答說有new的都是對象,對象便是類的實例化,本程序中,可以通過對Stars類進(jìn)行實例化從而創(chuàng)造出無數(shù)多個行星(理論上是的),但是內(nèi)部函數(shù)的實現(xiàn)有些問題難以解決,主要便在paintComponent()方法的重寫上,再次創(chuàng)建對象后,便會再次重寫該方法,于是會出現(xiàn)不可避免的問題,也是無法解決的一個遺憾!
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java面向?qū)ο蟪绦蛟O(shè)計入門與進(jìn)階教程》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設(shè)計有所幫助。
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)和算法中哈希表知識點詳解
在本篇文章里小編給大家分享了關(guān)于java數(shù)據(jù)結(jié)構(gòu)和算法中哈希表的相關(guān)知識點內(nèi)容,需要的朋友們學(xué)習(xí)下。2019-06-06
SpringBoot將多個文件夾進(jìn)行壓縮的兩種方法(瀏覽器下載和另存為)
Spring Boot項目通常不會自動對文件夾進(jìn)行壓縮,不過,在打包應(yīng)用時,如果你使用了Maven或Gradle這樣的構(gòu)建工具,并且配置了相應(yīng)的插件,可以在打成jar或war包的時候?qū)⒁蕾嚨膸煳募喜⒉嚎s,本文介紹了SpringBoot將多個文件夾進(jìn)行壓縮的兩種方法2024-07-07
java8 stream 操作map根據(jù)key或者value排序的實現(xiàn)
這篇文章主要介紹了java8 stream 操作map根據(jù)key或者value排序的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
springboot CompletableFuture并行計算及使用方法
CompletableFuture基于 Future 和 CompletionStage 接口,利用線程池、回調(diào)函數(shù)、異常處理、組合操作等機(jī)制,提供了強(qiáng)大而靈活的異步編程功能,這篇文章主要介紹了springboot CompletableFuture并行計算及使用方法,需要的朋友可以參考下2024-05-05
nacos注冊中心單節(jié)點ap架構(gòu)源碼解析(最新推薦)
這篇文章主要介紹了nacos注冊中心單節(jié)點ap架構(gòu)源碼解析,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01
MyBatisPlus的autoResultMap生成策略實現(xiàn)
本文主要介紹了MyBatisPlus的autoResultMap生成策略實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-02-02

