服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java编程实现的模拟行星运动示例

Java编程实现的模拟行星运动示例

2021-04-23 11:16wangbowj123 Java教程

这篇文章主要介绍了Java编程实现的模拟行星运动,涉及java基于swing组建绘制动态效果及数值运算相关操作技巧,并总结分析了java面向对象的相关特性,需要的朋友可以参考下

本文实例讲述了java编程实现的模拟行星运动。分享给大家供大家参考,具体如下:

期待了很久的java语言程序设计也拉下了帷幕,在几个月的时间里基本掌握了java的简单用法,学习了java的主要基础知识,面向对象思想,多线程并发控制,swing界面设计,动画制作等,最后结课了也打算制作一个课程设计能够尽可能多的涵盖所学知识,将其进行串联,因此考虑实现了一个简单的模拟行星运动的小软件,主要思路如下:

利用动画实现行星运动的模拟,主面板里有一个中心行星,同时绘制了椭圆轨道,有一颗运动的行星围绕着中心行星运动。同时右下角设置的有四个按钮,即“start”、“pause”、“accelerate”和“decelerate”分别可以使行星运动、暂停、加速、减速。

一、类的设计:

star继承自jpanel。star类是行星的基类,所有运动的行星都是继承自star类。内部draw()方法主要绘制了一个实心圆形,目的是在每次绘制时,可以保证中心行星始终显示。paintcomponent()方法重写了jpanel的绘制方法,目的是保证继承自star类的stars类的实例对象可以绘制出自己的行星。如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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类的对象,并且利用该对象,对线程进行操作。

设计如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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是设置背景图的部件。设计如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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编程实现的模拟行星运动示例

二、对象:

因为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程序设计有所帮助。

原文链接:https://blog.csdn.net/wangbowj123/article/details/76472789

延伸 · 阅读

精彩推荐