• Java课程设计——模拟行星运动


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

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

    一、类的设计:

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

     1 package Star;
     2 
     3 import java.awt.Color;
     4 import java.awt.Graphics;
     5 import javax.swing.JPanel;
     6 
     7 public class Star extends JPanel{
     8     /**
     9      * 基本的行星类
    10      */
    11     private static final long serialVersionUID = 1L;
    12     
    13     int x,y;
    14     int width,height;
    15     
    16     public Star() {
    17         width = 10;
    18         height = 10;
    19     }
    20     
    21     public Star(int x, int y){
    22         this.x = x;
    23         this.y = y;
    24         width = 10;
    25         height = 10;
    26     }
    27     
    28     public void draw(Graphics g){
    29         g.setColor(Color.blue);
    30         g.fillOval(x, y, width, height);
    31     }
    32     protected void paintComponent(Graphics g){
    33         super.paintComponent(g);
    34         g.fillOval(x, y, width, height);
    35     }
    36 }

    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 package Star;
      2 
      3 import java.awt.Color;
      4 import java.awt.Graphics;
      5 
      6 public class Stars extends Star{
      7     /**
      8      * 运动的行星
      9      */
     10     private static final long serialVersionUID = 1L;
     11 
     12     double alfa ;
     13     double speed ;
     14     Star center;
     15     int Long ; //长轴
     16     int Short;//短轴
     17     
     18     public Stars(int Px,int Py,Star center){
     19         super(Px,Py);
     20         this.center = center;
     21         Long = (Px - center.x)*2;
     22         Short = (Py - center.y)*2;
     23         this.setOpaque(true);
     24 //        move();
     25         alfa = 0;
     26         speed = 0.001;
     27     }
     28     
     29     protected void paintComponent(Graphics g){
     30         super.paintComponent(g);
     31         center.draw(g);//画出中心点
     32         move();
     33         g.setColor(Color.GREEN);
     34         g.drawOval(center.x-Long/2, center.y-Short/2, Long, Short);
     35     }
     36     
     37     public void move(){
     38         x = center.x + (int)(Long/2*Math.cos(alfa));
     39         y = center.y + (int)(Short/2*Math.sin(alfa));
     40         //沿椭圆轨迹运行
     41         alfa += speed; 
     42         //角度不断变化
     43     }
     44     
     45     class PThread extends Thread{ 
     46     //重画线程类
     47         private boolean suspend = true;
     48         private String control = "";
     49         public void run(){
     50             while(true){
     51                 synchronized (control) {
     52                     if(suspend){
     53                         //move();
     54                         repaint();
     55                     }
     56                 }
     57                 
     58             }
     59         }
     60         
     61         public void setsuspend(boolean s){
     62             //设置线程暂停方法
     63              if (!suspend) {
     64                  synchronized (control) {
     65                      control.notifyAll();
     66                  }
     67              }
     68             this.suspend = s;
     69         }
     70         
     71     }
     72     
     73     public PThread pt = new PThread();
     74     
     75     public void start(){
     76         pt.setsuspend(true);
     77         pt.start();
     78     }
     79     
     80     public void pause(){
     81         pt.setsuspend(false);
     82     }
     83     
     84     public void accelerate(){
     85         //加速的方法
     86         if(speed > 0){
     87             //角度每次加速0.0002
     88             speed += 0.0002;
     89         }
     90         else 
     91             speed = 0.001;
     92     }
     93     
     94     public void decelerate(){
     95         //减速的方法
     96         if(speed > 0){
     97             speed -= 0.0002;
     98             //角度每次减速0.0002
     99         }
    100         //若减速到0,则不能继续减速,另速度为0,停止运动
    101         else speed = 0;
    102     }
    103 }

    StarFrame类是本程序的启动面板,通过实例化该类,生成主程序界面,并且将行星部件,按钮,标签添加进面板。内部的getPanel()方法对两个按钮进行了设置,并且返回一个JPanel(将四个按钮添加进该JPanel中)。getLabel()方法返回一个文字描述的JLabel。Center对象是Star类的实例化,p1是Stars类的实例化,分别表示中心行星与环绕行星。jb1,jb2,jb3,jb4分别是行星的启动,暂停,加速,减速的控制按钮。image表示界面背景图,LayeredPanel是界面的层次面板,方便背景图的设置。jp,jl是设置背景图的部件。设计如下:

    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()方法的重写上,再次创建对象后,便会再次重写该方法,于是会出现不可避免的问题,也是无法解决的一个遗憾!

  • 相关阅读:
    1009 Product of Polynomials (25分)
    VS code 调试C++
    1065 A+B and C (64bit) (20分)
    UML与数据库应用系统
    语句(switch,异常,NDEBUG,assert)
    1046 Shortest Distance (20分)
    1042 Shuffling Machine (20分)
    模块和包
    闭包&装饰器
    迭代器、生成器
  • 原文地址:https://www.cnblogs.com/young-for-you/p/7286900.html
Copyright © 2020-2023  润新知