Introduction to Java

Introduction to Java
Jan Tobochnik and Harvey Gould

Java is an object-oriented programming language with a built-in application programming interface (API) that can handle graphics and user interfaces and be used to create applications or applets. Because of its rich set of API's, similar to the Macintosh and Windows, and its platform independence, Java can also be thought of as a platform in itself. Java also has standard libraries for doing mathematics.

Much of the syntax of Java is the same as C and C++. One major difference is that Java does not have pointers. However, the biggest difference is that you must write object oriented code in Java. Procedural pieces of code can only be embedded in objects.

Applications are programs which perform the same functions as those written in other programming languages. Applets are programs which are embedded in a Web page and thus can be accessed over the Internet. Our initial focus will be on writing applications. When a program is compiled, a byte code is produced which can be read and executed by any software that can run Java.

To use this tutorial you should run and study each program as you read along, so that you can see how added features affect the program.

Objects Constructors Private variables Extending a class
Graphics Offscreen Buffer User Interaction Animation
Threads Utility Package ControlFrame ControlMenu
Table Plot WorldGraphics Syntax Summary

Objects

Object-oriented programming focuses on constructs called "objects." An object consists of data and functions known as methods which use or change the data. A class defines what data can be in an object, and what operations are carried out by the methods. One or more objects and then be created or "instantiated" from a class. The structure of a Java program consists of various objects exchanging messages. In our first example we define the class Particle.
public class Particle {
   double x, y, vx, vy, mass;
}
This class does not do anything but can be used to describe a particle by its position, velocity, and mass. For simplicity, we will consider only two dimensions.

Constructors

We need to do something to initialize a class. Every class has at least one constructor, a method which has the same name as the class. The purpose of a constructor is to perform the necessary initialization for the new object.

public class Particle {
   double x, y, vx, vy, mass;  // these can be used by any method in the class
   
   // example of constructor method
   public Particle(double x, double y, double vx, double vy, double mass) {
      this.x = x;    
      this.y = y;
      this.vx = vx;    
      this.vy = vy;
      this.mass = mass;
   }
}
The above constructor allows us to specify the initial position and velocity of the particle and the value of its mass. The parameters x,y,vx,vy, and mass are the arguments of the constructor. We say that Particle is the constructor for the Particle class. We have already used the following characteristics of Java: Sometimes we want to initialize an object in several different ways as in the following example.
public class Particle {
   double x, y, vx, vy, mass;
   
   // examples of constructors
   
   public Particle() {
   }
   
   public Particle(double x, double y, double vx, double vy, double mass) {
      this.x = x; this.y = y; this.vx = vx; this.vy = vy; this.mass = mass;
   }

   public Particle(double x, double y) {
         this(x,y,0,0,1);
   }

   public Particle(double x, double y, double m) {
      this(x,y,0,0,m);
   }
   
   public Particle(double x, double y, double vx, double vy) {
      this(x,y,vx,vy,1);
   }
}

We next give an example of a Particle class with some useful methods. We will omit the velocity components for now.

public class Particle {
   double x, y, mass;
      
   public Particle() {
   }

   public Particle(double x, double y) {
      this(x,y,1);
   }
   
   public Particle(double x, double y, double mass) {
      this.x = x; this.y = y; this.mass = mass;
   }
   
   public double getWeight() {
      return 9.8 * mass;
   }

   public double distanceFromOrigin() {
      return Math.sqrt(x*x + y*y);
   }
}

  • Note that we have added methods to compute the weight of a particle and its distance from the origin.

  • The fundamental parts of a method are its name, arguments, return type, and the body. Methods can be created only as part of a class. By convention, method names begin with a lower case.

  • Note the use of return to return a value to the caller of a method.

  • The method distanceFromOrigin in the class Particle computes the distance of a particle from the origin using the particle coordinates x and y. The square root function Math.sqrt in this calculation is part of the Math class, a library of mathematical functions which consists of a collection of static methods. We will postpone a discussion of such classes, but their use is clear from the context.

    A program consists of one or more class definitions, which should be in separate files. The name of the file should be the same as the name of the class, for example, MyApplication.java. One of these clases must define a method main. We next show a simple program that creates two objects of type Particle.

    public class MyApplication {
    
       public static void main(String[] args) {
         Particle a = new Particle(1.0,1.0);        // create an instance of Particle called a
         System.out.println(a.distanceFromOrigin());
         System.out.println(a.mass);
         Particle b;
         b = new Particle();
         b.x = 2.0;
         b.y = 3.0;
         b.mass = 3;
         System.out.println(b.distanceFromOrigin());
         System.out.println(b.mass);
         System.out.println(b.getWeight());
       }
    }
    

    Private variables

    Java uses three explicit keywords and one implied keyword to set the boundaries in a class. The default access specifier for variables and methods is "package visibility" which means that all the other classes in the current package have access to them. Packages are Java's way of making libraries and will be discussed later. The specifier public provides access to anyone, private provides access only to methods within the same class, and protected provides access to methods in the same package and to all subclasses even if they are in different packages.

    Ideally, the variables in the Particle class should be declared private. Make x private and see what happens when you run MyApplication.

    If we declare x, y, and mass as private variables, we have to write methods in Particle so that another class can access the variable information in Particle. For simplicity, we will consider only the variable x. Our particle class becomes:

    public class Particle {
       private double x;
       private double mass;
    
       public Particle(double x, double mass) {
          this.x = x; 
          this.mass = mass;
       }
    
       public Particle(double x) {
          this(x, 1.0);
       }
       
       public double getX() {
          return x;
       }
    
       public void setX(double newX) {
          x = newX;
       }
    
       public double getWeight() {
          return 9.8 * mass;
       }
       
       public double distanceFromOrigin() {
          return Math.abs(x);
       }
    
    }
    

    Note the new methods getX and setX. They are used in the following.

    public class MyApplication {
       public static void main(String[] args) {
       Particle p = new Particle(10.0, 2.0);
       System.out.println(p.distanceFromOrigin());
       System.out.println(p.getX());  // would have written p.x if x were public
       System.out.println(p.getWeight());
       p.setX(3.0);    // change value of x
       System.out.println(p.getX());
       System.out.println(p.distanceFromOrigin());
       }
    }
    


    Extending a class

    Now that we have defined a particle class, we can extend it to consider charged particles for example. That is, we want a new class ChargedParticle, that has all the functionality of Particle, but also has the ability to have a charge. We can implement ChargedParticle as an extension or subclass of Particle as shown below.

    public class ChargedParticle extends Particle {
       // magnitude of electron charge in Coulombs
       public static final double ELQ = 1.602e-19;
       private int charge;
       
       public ChargedParticle(double x,double y, double mass, int charge) {
          super(x,y,mass);     // constructor for Particle
          this.charge = charge;
       }
    
       public int getCharge() {
          return charge;
       }
       
       public void setCharge(int newCharge) {
          charge = newCharge;
       }
    
       public static int netCharge(ChargedParticle a, ChargedParticle b) {
          return a.charge + b.charge;
       }
    }
    
    An example of the use of this new class is given below.
    public class MyApplication {
          public static void main(String[] args) {
          ChargedParticle a = new ChargedParticle(10.0,0,0,1);
          System.out.println(a.distanceFromOrigin());
          System.out.println(a.getCharge());
          System.out.println(ChargedParticle.ELQ*a.getCharge());
          ChargedParticle b = new ChargedParticle(-5.0,0,0,-1);
          System.out.println(b.distanceFromOrigin());
          System.out.println(ChargedParticle.netCharge(a,b));
          b.setCharge(3);
          System.out.println(ChargedParticle.netCharge(a,b));
          }
       }
    

    The following example illustrates the nature of static variables:

    public class Test {
       public static int x = 0;
       public int y = 0;
    
       public String showxandy() {
          return "x = " + x + ", y = " + y;
       }
    
       public static void main(String[] args) {
          Test a = new Test();
          Test b = new Test();
    
          a.x = 5;     // static variable
          a.y = 12;    // instance variable
          System.out.println(a.showxandy());      // outputs 5, 12
          b.x = 7;
          b.y = 13;
          System.out.println(a.showxandy());      // outputs 7, 12
          System.out.println(b.showxandy());      // outputs 7, 13
          Test.x = 2;
          System.out.println(a.showxandy());      // outputs 2, 12
          System.out.println(b.showxandy());      // outputs 2, 13
       }
    }
    
    The (static) x variable belongs to class Test and hence belongs to a and b. In contrast, y belongs to the instances of the class test and hence a.y and b.y are distinct variables.

    The String type is unique among all classes in that it is the only class to support an operator: the + operator can be used to concatenate strings. When a number is concatenated with a string, the number is converted to a string.

    Graphics

    A powerful feature of Java is its simple to use graphics. As an example we will draw the trajectory of a particle in projectile motion. To do this we add to Particle the method step to integrate the equations of motion one time step forward. The arguments of step are the time step and the Force on the particle, which is defined below in another class. We also add other methods which will be useful.

    public class Particle {	
    
      private double x,y,vx,vy,ax,ay;
      private double mass = 1.0;
      private boolean firststep = true;
    
    	public Particle(double x, double y, double vx, double vy) {
    		this.x = x;
    		this.y = y;
    		this.vx = vx;
    		this.vy = vy;
    	}
    
     public double getMass() {
            return mass;
     }
    
     public void setMass(double mass) {
            this.mass = mass;
     }
    
    	public double getX() {
    		return x;
    	}
    
    	public double getY() {
    		return y;
    	}
    
    	public double getVX() {
    		return vx;
    	}
    
    	public double getVY() {
    		return vy;
    	}
    
    	public double getAX() {
    		return ax;
    	}
    
    	public double getAY() {
    		return ay;
    	}
    
    	public void setX(double x) {
    		this.x = x;
    	}
    
    	public void setY(double y) {
    		this.y = y;
    	}
    
    	public void setVX(double vx) {
    		this.vx = vx;
    	}
    
    	public void setVY(double vy) {
    		this.vy = vy;
    	}
    
    	public void step(double dt, Force f) {
      if(firststep) {
        ax = f.getfx(x,y,vx,vy,this)/mass;  // acceleration at beginning of interval
        ay = f.getfy(x,y,vx,vy,this)/mass;
        firststep = false;
      }
    		double vxm = vx + 0.5*ax*dt;    // velocity at middle of interval
    		double vym = vy + 0.5*ay*dt;
    		double xm = x + 0.5*vx*dt;      // position at middle of interval
    		double ym = y + 0.5*vy*dt;
    	 double axm = f.getfx(xm,ym,vxm,vym,this)/mass;   
    	 double aym = f.getfy(xm,ym,vxm,vym,this)/mass;
    		vx += axm*dt;            // velocity at end of interval
    		vy += aym*dt;
    		x += vxm*dt;           // position at end of interval
    		y += vym*dt;
    	 ax = f.getfx(x,y,vx,vy,this)/mass;  // acceleration at end of interval
    	 ay = f.getfy(x,y,vx,vy,this)/mass;
    	}
    
    }
    
    
    
    public class Force {
       
       private final static double g = 9.8;
       double b = 0;   // used in drag force
       
       public void setb(double b) {
         this.b = b;
       }
       
       public double getfx(double x, double y, double vx, double vy, Particle p) {
         return -b*vx;
       }
       
       public double getfy(double x, double y, double vx, double vy, Particle p) {
         return -b*vy - g*p.getMass();
       }
       
    }
    

    The step method uses the Euler-Richardson integration algorithm. The first time the algorithm is used we need to compute the acceleration at the beginning of the interval. After that we can use the acceleration computed at the end of the previous interval. Note how this is used in the step method to refer to the Particle itself, and then in Force we use the argument Particle to get the particle's mass.

    The class which draws the trajectory is given below.

    import java.awt.*;
    
    public class ParticleSystem extends Frame {
            public static void main(String[] args) {
                    ParticleSystem ps = new ParticleSystem();   // set up window for application
            }
            
            public ParticleSystem() {     // constructor
                    setSize(512, 342);
                    setVisible(true);
            }
    
            public void paint(Graphics g) {
                    setBackground(Color.white);
                    calculateTrajectory(g);
            }
    
            private void calculateTrajectory(Graphics g) {
                    final double tmax = 10.0;
                    final double dt = 0.5;
                    Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
                    Force f = new Force();
                    g.setColor(Color.blue);
                    double time = 0.0;
                    while (time < tmax) {
                            g.drawOval((int)p.getX(),
                                    getSize().height - (int)p.getY(), 10, 10);  //draw circle of diameter 10 pixels
                            p.step(dt,f);
                            time += dt;
                    }
            }
    }
    
    


    Offscreen buffers

    When you click on another application covering up the frame, and then come back to your program, Java automatically calls paint. This is nice, however in the above program it means that you must recompute the trajectory. A better approach is to first draw to an offscreen image buffer and then blast this buffer to the screen. As long as the buffer is saved no new calculations are done. First we will show how this is done for the above ParticleSystem class and then we will show an example where it is more useful.

     
    import java.awt.*;
    
    public class ParticleSystem extends Frame {
        Image offscreen;
        
            public static void main(String[] args) {
                    ParticleSystem ps = new ParticleSystem();   // set up window for application
            }
            
            public ParticleSystem() {     // constructor
                    setSize(512, 342);
                    setVisible(true);
                    offscreen = createImage(getSize().width, getSize().height);
                    calculateTrajectory();
            }
    
            public void paint(Graphics g) {
                    setBackground(Color.white);
                    g.drawImage(offscreen, 0, 0, this);   // draw image onto screen
            }
    
            public void calculateTrajectory() {
                    final double tmax = 10.0;
                    final double dt = 0.5;
                    Graphics g = offscreen.getGraphics();
                    g.setColor(Color.blue);
                    Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
                    Force f = new Force();
                    double time = 0.0;
                    while (time < tmax) {
                            g.drawOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
                            p.step(dt,f);
                            time += dt;
                    }
            }
    }
    
    


    User Interaction

    Offscreen buffers are useful when we want the user to be able to draw more than one trajectory without running the program over again. To do this we want the user to interact with the program. This feature is very easy to accomplish in Java using components such as Buttons, TextFields, and Menus. Below we show how to use a TextField to receive a number from the user. We put the TextField on a separate Frame and use an actionListener to detect whether the user enters a number in the TextField. The number entered will be the friction coefficient, b,used in a drag force of the form -bv.

     import java.awt.*;
     import java.awt.event.*;   // needed for actionListener
        
     class FrictionInput extends Frame {
        TextField tf;
        Label l;
        ParticleSystem ps;
       
       public FrictionInput (ParticleSystem ps) {
          this.ps = ps;
                 setUpFrame();
       }
    
       public void setUpFrame() {
                setTitle("Friction Input");
                setSize(200,100);
                setLocation(400,50);
                setLayout(null);   // not using any layout manager
                l= new Label("Friction Coefficient");      // new label for textfield
                l.setSize(150,20);
                l.setLocation(30,70);
                add(l);                                 // add label
                tf = new TextField();  // new textfield
                tf.addActionListener( new T());          // add listener 
                tf.setSize(50,20);
                tf.setLocation(30,40);
                add(tf);                                  // add textfield
                setVisible(true);
        }
                
      class T implements ActionListener {    // Internal class
                 
             public void actionPerformed(ActionEvent e) {
                 Double R = new Double(tf.getText().trim());
             ps.calculateTrajectory(R.doubleValue());
         } 
      }  
    } 
    
    

    The following modification of ParticleSystem uses FrictionInput.

    import java.awt.*;
    
    public class ParticleSystem extends Frame {
        private Image offscreen;    
        private int counter = 0;  // used to change color for each trajectory
        
            public static void main(String[] args) {
                    ParticleSystem ps = new ParticleSystem();   // set up window for application
                    FrictionInput fi = new FrictionInput(ps);   // set up window for application
            }
            
            public ParticleSystem() {     // constructor
                    setSize(512, 342);
                    setVisible(true);
                    offscreen = createImage(getSize().width, getSize().height); 
            }
    
            public void paint(Graphics g) {
                    setBackground(Color.white);
                    g.drawImage(offscreen, 0, 0, this);   // draw image onto screen
            }
    
            public void calculateTrajectory(double b) {
                    final double tmax = 10.0;
                    final double dt = 0.5;
                    Graphics g = offscreen.getGraphics();   // create buffer
                    changeColor(g);
                    Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
      Force f = new Force();
      f.setb(b);
                    double time = 0.0;
                    while (time < tmax) {
                            g.drawOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
                            p.step(dt,f);
                            time += dt;
                    }
              repaint();
            }
            
       public void changeColor(Graphics g) {
                    switch(counter++) {                     //counter increased by 1
                        case 0: g.setColor(Color.red);break;
                        case 1: g.setColor(Color.blue);break;
                        case 2: g.setColor(Color.green);break;
                        case 3: g.setColor(Color.yellow);break;
                        case 4: g.setColor(Color.magenta);break;
                        case 5: g.setColor(Color.orange);break;
                        case 6: g.setColor(Color.cyan);break;
                        case 7: g.setColor(Color.pink);break;
                        default : g.setColor(Color.black);
                }
      }
    }
    

    Animation

    We now return to a single trajectory and discuss animation. Instead of showing the trajectory we will simply show a ball as it moves. The following code does this so that there is very little flicker. We have reduced the time step so that the motion of the ball will be slowed down.

    import java.awt.*;
    
    public class ParticleSystem extends Frame {
        Image offscreen;
        
            public static void main(String[] args) {
                    ParticleSystem ps = new ParticleSystem();   // set up window for application
                    ps.calculateTrajectory();
            }
            
            public ParticleSystem() {     // constructor
                    setSize(512, 342);
                    setVisible(true);
                    offscreen = createImage(getSize().width, getSize().height);
            }
    
          
            public void paint(Graphics g) {
                    setBackground(Color.white);
                    g.drawImage(offscreen,0,0,this);
            }
    
            public void calculateTrajectory() {
                    final double tmax = 10.0;
                    final double dt = 0.005;
                    Graphics b = offscreen.getGraphics();
                    Particle p = new Particle(0.0, 200.0, 40.0, 25.0);
                    Force f = new Force();
                    double time = 0.0;
                    while (time < tmax) {
                     Rectangle oldRect = new Rectangle((int)p.getX(),getSize().height -(int)p.getY(),11,11);
                     p.step(dt,f);
                     time += dt;
                     Rectangle newRect = new Rectangle((int)p.getX(),getSize().height -(int)p.getY(),11,11);  // new region of ball
                     Rectangle r = newRect.union(oldRect);           // new plus old region
                     b.clearRect(r.x,r.y,r.width,r.height);    // clear new plus old region on buffer
                     b.fillOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
                     Graphics g = getGraphics();
                     g.drawImage(offscreen,0,0,this);
                }
            }
    }
    
    

    The basic stategy used above is to define three rectangles. One containing the old position of the ball, one containing the new position, and one which is the union of the two. Then we clear the buffer of this latter rectangle, and draw our new ball. We then draw our image to the screen. Note how we grab the Graphics object for the screen within calculateTrajectory instead of using repaint. This avoids some of the flickering that would occur from clearing the Frame.



    Threads

    Often we want the user to be able to interupt a simulation while it is running, and then start it going again. For example, we might want to know the coodinates of our ball at some instant while we are watching it. One can use Threads to accomplish this. Basically, a Thread is a process whcih is running parallel to another process. Below we set up a Thread and use a MouseListener to interupt the program. The interface Runnable contains the methods we need to start, stop, and run the Thread.

    import java.awt.*; 
    import java.awt.event.*;
    
    public class ParticleSystem extends Frame implements MouseListener, Runnable {
      Image offscreen;
      Graphics gb;
      Particle p;
      Force f;
      boolean running = false;
      Thread runner;
        
    public static void main(String[] args) {
      ParticleSystem ps = new ParticleSystem();   // set up window for application
    }
            
    public ParticleSystem() {     // constructor
      setSize(512, 342);
      setVisible(true);
      offscreen = createImage(getSize().width, getSize().height);
      p = new Particle(0.0, 200.0, 40.0, 25.0);
      f = new Force();
      gb = offscreen.getGraphics();
      start();
      addMouseListener(this);    
    }
    
          
    public void paint(Graphics g) {
      setBackground(Color.white);
      g.drawImage(offscreen,0,0,this);
    }
        
    public void start() {
      runner = new Thread(this);
      runner.start();
    }
    
    public void stop() {
      runner.stop();
    }
    
    public void run() {
      while(true) {
        try {Thread.sleep(5);}  // delay 5 msec between updates
        catch (InterruptedException e){};
        if(running) calculateTrajectory();
      }
    }
    
    public void mouseClicked(MouseEvent e) {
      Graphics g = getGraphics();
      g.clearRect(0,0,getSize().width, getSize().height);
      g.fillOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
      g.drawString("x = " + String.valueOf(p.getX()),e.getX(),e.getY());
      g.drawString("y = " + String.valueOf(p.getY()),e.getX(),e.getY() + 30);
      running = false;
    }
    public void mouseEntered(MouseEvent e) {running = true;}
    public void mouseExited(MouseEvent e) {running = false;}
    public void mousePressed(MouseEvent e) {}
    public void mouseReleased(MouseEvent e) {}
    
    public void calculateTrajectory() {
      private final double dt = 0.005;
      Rectangle oldRect = new Rectangle((int)p.getX(),getSize().height -(int)p.getY(),11,11);
      p.step(dt, f);
      time += dt;
      Rectangle newRect = new Rectangle((int)p.getX(),getSize().height -(int)p.getY(),11,11);  
      Rectangle r = newRect.union(oldRect);           
      gb.clearRect(r.x,r.y,r.width,r.height);    
      gb.fillOval((int)p.getX(), getSize().height - (int)p.getY(), 10, 10);
      Graphics g = getGraphics();
      g.drawImage(offscreen,0,0,this);
    }
    }
    
    

    We have modified calculateTrajectory so that it only computes and draws one step. We have eliminated the while statement. Instead control of the trajectory is given to the run method of the Thread runner. Note the code within this method. The try catch statement is used to interupt the Thread for 5 milliseconds to check to see if any event occurred. The MouseListener checks for events. In this case we can stop the motion by moving the mouse outside the Frame, and start it again by moving it into the Frame. If the mouse is clicked we write the x and y coodinates of the ball at the location of the mouseclick, redraw the ball, and stop the motion.


    Utility Package

    We now provide the following general purpose classes. You can use these classes without knowing the details of how they are implemented. The classes are part of a Java package called simphy. To use these files you need to add import simphy.*; to any file using classes in the package. Arrays are used heavily in the classes shown below. Note how they are declared, instantiated, and in many cases initiated. To modify any of these classes you can write your own which extends the class.


    Constructors and other methods for general purpose classes.
    //constructors
    public ControlFrame(MySimulation S, String lstring[], String bstring[]) 
    public ControlFrame(MySimulation S, String lstring[], double x[], String bstring[]) 
      // use if have initial values x[]
    
    /*  MySimulation implements Simulation
    
        lstring is an array of names for the labels under the TextFields
        x is an array of initial values for the TextFields
        bstring is an array of names for the Buttons
    
        You can also use the following methods to place values in the TextFields   
    */
    
       public void setText(int k, String s) 
    
       public void setText(int k, int x) 
       
       public void setText(int k, double x) 
      
    
    //constructors
    public ControlMenu(MySimulation S, String lstring[], String bstring[]) 
    public ControlMenu(MySimulation S, String lstring[], double x[], String bstring[]) // use if have
    initial values
    
    /*  MySimulation implements Simulation
    
        lstring is an array of names for the parameter menu
        x is an array of initial values for the parameters
        bstring is an array of names for the action menu
       
       ControlMenu uses InputDialog class.
       
    */
        
    public interface simulation
    
       public void buttonAction(int k);
       
       public void textAction(int k, double x);
       
       public void menuAction(int k);
       
       public void dialogAction(int k, double x);
    
    
    //constructor
    public Table(String TableName String h[])   // h is an array of table headings
    
    // methods
    
    public void setHeadings(String h[])   // display new table headings
    
    public void setFormat(String pattern[],int FieldSize) 
     
    /* Set format for table entries. Fieldsize is maximum size for each number, pattern[k]  
    is the pattern for kth number. Ex. "#.000"  prints 3 decimal places. */
    
    public void setEntry(int i, double x) // set ith value equal to x for next row to be displayed
    
    public void setEntry(double x0, double x1) // set first two values
    
    public void setEntry(double x0, double x1, double x2) // set first three values
    
    public void setEntry(double x0, double x1, double x2, double x3) // set first four values
    
    public void addEntries()  // display next row
    
    
    
    //constructors
     public Plot(String title, String xLabel, String yLabel, int nAxes, 
             double xmin,double xmax, double ymin, double ymax)
    
     public Plot(String title, String xLabel, String yLabel, int nAxes, 
             double xmin,double xmax, double ymin, double ymax, int symbolSize, String symbolType) {
     
     public Plot(int nAxes,double xmin,double xmax, double ymin, double ymax) {
    
        
    /* nAxes = 1, one bottom horizontal axis, ymin should = 0
       nAxes = 2, one left vertical axis, one bottom horizontal axis, xmin and ymin should = 0
       nAxes = 3, one center vertical axis, one bottom horizontal axis, xmin should = -xmax, ymin should = 0
       nAxes = 4, crossed axes, xmin should = -xmax and ymin should = -ymax
       nAxes = 5, crossed axes, only x > 0, xmin should = 0 and ymin should = -ymax
       nAxes = anything else, no axes drawn.  
       symbolType = "fillsquare" or "opensquare" or "opencircle" or "fillcircle"
       symbolSize = 1 for point (default), otherwise gives size in pixels */
    
      public void plotPoints(double x[], double y[]);
    
    //constructor
      public WorldGraphics(String title, 
             double xmin,double xmax, double ymin, double ymax) {
    
      (xmin,ymin) are the coordinates for the lower left hand corner of the Frame.   
      (xmax,ymmax) are the coordinates for the upper right hand corner of the Frame. 
    
      methods have the same name as those in the Jave Graphics class.
    
    

    A test example of how these classes are instantiated is shown below. Try running this program and testing the Buttons, TextFields, and menu items. Find the code in the program for the things you see on the screen.
    
    import simphy.*;
    
    public class Utilities {
     public static void main(String args[]) { 
          Utilities u = new  Utilities();
     }  
    
    
     public Utilities() {
           String h[] = {"first","second","third"};
           Table tb = new Table("test",h);   
           String pattern[] = {"#.0000", "#.00","#.000"};
           tb.setFormat(pattern,10);
           tb.setEntry(0,3.173);
           tb.setEntry(1,999.9173);
           tb.setEntry(2,3891.73);
           tb.addEntries();
           tb.setEntry(3317.3,99.173,817.3);
           tb.addEntries();
           MySimulation S = new MySimulation();
           String lString[] = {"zero", "one", "two","three", "four", "five","six", "seven", "eight"};
           String bString[] = {"A", "B", "C","D", "E", "F","G", "H", "I"};
           double initialP[] = { 1,2,3,4,5,6,7,8,9};
           ControlFrame cf = new  ControlFrame(S,lString,initialP,bString);
           ControlMenu cm = new  ControlMenu(S,lString,initialP,bString);
           WorldGraphics v = new WorldGraphics("Visualization",0,10,0,10);
           v.setMenuBar(cm.sBar);
           S.notify(cm);
           S.notify(v);
           S.notify(cf);
         }
     }
    

    An example of a Simulation class is shown below. If performs a number of arbitrary operations and shows communication between the different objects using the notify methods. Note that because it implements Simulation it must include implementations of the methods in the Simulation interface. This insures that ControlFrame and ControlMenu will work properly.
    import java.awt.*;
    import simphy.*;
    
    public class MySimulation implements Simulation{
       ControlMenu cm;
       ControlFrame cf;
       WorldGraphics v;
    
       public void buttonAction(int k) {
         double x[] = {0,1,2,3,4};
         double y[] = {0,1,2,3,4};
         switch(k) {
          case 0: Plot p =  new Plot("y vs x","xxxx","yyyy",1,-5,5,0,5);p.plotPoints(x,y);break;
          case 1: Plot p1 = new Plot("y vs x","xxxx","yyyy",2,-5,5,0,5);p.plotPoints(x,y);break;
          case 2: Plot p2 = new Plot("y vs x","xxxx","yyyy",3,-5,5,0,5);p.plotPoints(x,y);break;
          case 3: Plot p3 = new Plot("y vs x","xxxx","yyyy",4,-5,5,0,5);p.plotPoints(x,y);break;
       }
       
     }
         
       public void textAction(int k, double x) {
          System.out.println(x);
          cf.setText(0,x);
          cf.setText(1,(int) x);
          cf.setText(2,"hello " + String.valueOf(k));
       }
       
       public void menuAction(int k) { 
         switch(k) {
          case 0: v.drawRect(5,5,4,4.0); break;
          case 1: v.drawString("good job", 7.0,2.0);break;
          case 2: v.drawLine(0,0,10,10);break;
          case 3: v.drawRect(200,200,100,100);break;
          case 4: v.drawCircle(5,5,3);break;
          case 5: v.clearRect(0,0,10,10);break;
          case 6: v.setColor("yellow");break;
          case 7: v.setColor("green");break;
          case 8: v.setColor("random");break;
         }
         cf.texts[1].setText(String.valueOf(k));  // shows which menu selected in a TextField
       }
       
       public void dialogAction(int k, double x) {
           System.out.println(x);
       }
       
       public void notify(ControlMenu cm) {
          this.cm = cm;
       }
    
       public void notify(ControlFrame cf) {
          this.cf = cf;
       }
      
       public void notify(WorldGraphics v ) {
          this.v = v;
       }
    }
    

    Class and interface Listings
    
    package simphy;
    
    public interface Simulation {   // used with ControlFrame or ControlMenu
    
       public void buttonAction(int k);
       
       public void textAction(int k, double x);
       
       public void menuAction(int k);
       
       public void dialogAction(int k, double x);
       
    }
    
    
    
    package simphy;
    
     import java.awt.*;
     import java.awt.event.*;
        
     public class ControlFrame extends Frame {
        public TextField texts[];
        Label labels[];
        Button buttons[];
        Simulation S;
        String lString[], bString[];
        double x[];
       
       public ControlFrame(Simulation S, String lString[], String bString[]) {
                this.S = S;
              this.lString = lString;
              this.bString = bString;
              int nT = lString.length;
              x = new double[nT];
              for(int i = 0; i < nT;i++)
                x[i] = 0.0;
              setUpFrame();
       }
    
       public ControlFrame(Simulation S, String lString[], double x[], String bString[]) {
                this.S = S;
              this.lString = lString;
              this.bString = bString;
              this.x = x;
              setUpFrame();
       }
       
       public void setUpFrame() {
              int ix = 20, iy = 20,bxT = 100,by = 20, ysep = 80, lsep = 20 ;
              int fSize = 0, bx;
              int nT = lString.length;      // number of textfields
              int nB = bString.length;      // number of buttons
              for (int i = 0; i < nB; i++) 
                  fSize += 20 + max(bString[i].length()*10,bxT);
              for (int i = 0; i < nT; i++) 
                  fSize += 20 + max(lString[i].length()*10,bxT);
              if(fSize < 500) 
                  setSize(fSize, ysep);
              else {
                  setSize(500, (1 + fSize/500)*ysep);
                  fSize = 500;
              }
              setTitle("Controls");
              this.S = S;
              setLayout(null);
              texts = new TextField[nT];    // new array of textfields
              labels = new Label[nT];       // new array of labels
              buttons = new Button[nB];     // new array of buttons
    
             for(int i = 0; i < nB;i++) {
                bx = max(bString[i].length()*10,bxT);   // button size
                if(ix + bx + 20 > fSize){
                   ix = 20;
                   iy += ysep;
                }
                buttons[i] = new Button(bString[i]);      // new button
                buttons[i].addActionListener(new B(i));  // add listener
                buttons[i].setSize(bx,by);
                buttons[i].setLocation(ix,iy);
                add(buttons[i]);                                // add button
                ix += bx + 20;
               } 
             for(int i = 0; i < nT;i++) {
                bx = max(lString[i].length()*10,bxT);   // label size
                if(ix + bx + 20 > fSize){
                   ix = 20;
                   iy += ysep;
                }
                labels[i]= new Label(lString[i]);               // new label for textfield
                labels[i].setSize(bx,by);
                labels[i].setLocation(ix,iy+lsep);
                add(labels[i]);    // add label
                if( (int) x[i] == x[i])                               
                  texts[i]= new TextField(String.valueOf( (int) x[i]));  // new textfield
                else
                  texts[i]= new TextField(String.valueOf(x[i]));  // new textfield
                texts[i].addActionListener( new T(i));          // add listener 
                texts[i].setSize(bxT,by);
                texts[i].setLocation(ix,iy);
                add(texts[i]);                                  // add textfield
                ix +=  bx + 20;
               }
             setVisible(true);
             
        }
        
       private int max(int a, int b) {
          if ( a > b) 
             return a;
          else
             return b;
       }
    
       public void setText(int k, String s) {
          texts[k].setText(s);
       }
    
       public void setText(int k, int x) {
          texts[k].setText(String.valueOf(x));
       }
       
       public void setText(int k, double x) {
          texts[k].setText(String.valueOf(x));
       }
                
    // Inner classes
                
       class B implements ActionListener {
               int k;    // kth button
                 
             public B(int k) {
                   this.k = k;
             }
                 
             public void actionPerformed(ActionEvent e) {
                    S.buttonAction(k);
             } 
      }  
                
       class T implements ActionListener {
             int k;   // kth TextField
                 
             public T(int k) {
                this.k = k;
             }
                 
             public void actionPerformed(ActionEvent e) {
                  Double R = new Double(texts[k].getText().trim());
                    S.textAction(k,R.doubleValue());
               } 
         }  
                
    }
                
    
                
    
    
    
    package simphy;
    import java.awt.*;
    import java.awt.event.*;
    
    public class ControlMenu  {
    
       public MenuBar sBar;          // declare menubar
       Menu bMenu,tMenu;             // declare two menus
       MenuItem bItems[];            // declare array of menu items
       MenuItem tItems[];            // declare array of menu items
       Simulation S;
       String lString[], bString[];
       double x[];
       
       public ControlMenu(Simulation S, String lString[], String bString[]) {
          this.S = S;
              this.lString = lString;
              this.bString = bString;
              int nT = lString.length;
              x = new double[nT];
              for(int i = 0; i < nT;i++)
                x[i] = 0.0;
              setUpMenu();
       }
    
       public ControlMenu(Simulation S, String lString[], double x[], String bString[]) {
          this.S = S;
              this.lString = lString;
              this.bString = bString;
              this.x = x;
              setUpMenu();
       }
       
       public void setUpMenu() {
          sBar = new MenuBar();                    // assign menubar
          bMenu = new Menu("Actions");             // assign menu
          tMenu = new Menu("Parameters");          // assign menu
          sBar.add(bMenu);                         // add menu to menubar
              sBar.add(tMenu);                         // add menu to menubar
              int nB = bString.length;
              bItems = new MenuItem[nB];               // assign array of menu items
              int nT = lString.length;
              tItems = new MenuItem[nT];               // assign array of menu items
    
              for(int i = 0; i < nT;i++) {
                tItems[i] = new MenuItem(lString[i]);  // assign menu item to array element
                tItems[i].addActionListener( new T(i));
                tMenu.add(tItems[i]); }                // add menu item to menu
              for(int i = 0; i < nB;i++) {
                bItems[i] = new MenuItem(bString[i]);  // assign menu item to array element
                bItems[i].addActionListener( new B(i));
                bMenu.add(bItems[i]); }                // add menu item to menu
               } 
        
        class B implements ActionListener {
                 int k;
                 
                 public B(int k) {
                   this.k = k;
                 }
                 
                 public void actionPerformed(ActionEvent e) {
                    S.menuAction(k);
                 } 
             }  
                
             class T implements ActionListener {
                 int k;
                 
                 public T(int k) {
                   this.k = k;
                 }
                 
                 public void actionPerformed(ActionEvent e) {
                   InputDialog d = new InputDialog(S,k,lString[k],x);
             }
        }
     
     }
      
                
    package simphy;
    import java.awt.*;
    import java.awt.event.*;
    
    class InputDialog extends Frame {    // Used with ControlMenu
       
       TextField newValueText;
       double x[];
    
       public InputDialog(Simulation S,int k, String lString, double x[]) {
          this.x = x;
          setTitle("Dialog Box");
          setSize(250,250);
          setLocation(50,50);
          setLayout(null);
          Label label = new Label("Enter new  " + lString);
          label.setSize(150,20);
          label.setLocation(50,20);
          add(label);
          Button b1 = new Button("Okay");
          b1.addActionListener( new OkayClass(k,S));
          Button b2 = new Button("Cancel");
          b2.addActionListener( new CancelClass());
          b1.setLocation(30,80);
          b2.setLocation(150,80);
          b1.setSize(70,20);
          b2.setSize(70,20);
          add(b1);
          add(b2);
          newValueText = new TextField(String.valueOf(x[k]));
          newValueText.setSize(80,20);
          newValueText.setLocation(50,50);
          add(newValueText);
    
          setVisible(true);
       }
    
      class OkayClass implements ActionListener{
      
          int k;
          Simulation S;
      
          public OkayClass(int k, Simulation S) {
             this.k = k;
             this.S = S;
          }
          
          public void actionPerformed(ActionEvent e) {
              String s = newValueText.getText();
              Double R = new Double(s.trim());
              S.dialogAction(k,R.doubleValue());
              x[k] = R.doubleValue();
              setVisible(false);
              dispose();
          }
       }
    
       class CancelClass implements ActionListener{
      
          public void actionPerformed(ActionEvent e) {
              setVisible(false);
              dispose();
          }
       }
        
    
    }
    
    
    package simphy;
    import java.awt.*;
    import java.text.*;
    
    
    public class Table extends Frame {
    
       protected double entry[];
       int n;
       public TextArea t;
       DecimalFormat number[];
       int FieldSize = 10; 
    
       
       public Table(String TableName, String h[]) {   // sets up Table with default formats
          n = h.length;
          entry = new double[n];
          number = new DecimalFormat[n];
          setTitle(TableName);
          setSize(500,500);
          t = new TextArea();
          add(t);
          setVisible(true);
          setHeadings(h);
          String pattern[] = new String[n];
          for(int i = 0; i < n ; i++) 
             pattern[i] = "#.000";
          setFormat(pattern,FieldSize);
       }
       
       public void setHeadings(String h[]) {
          int len;
          setFont(new Font("Monospaced",Font.BOLD,10));
          for(int i = 0; i < n ; i++) {
             len = h[i].length();
             if(len < FieldSize) 
                for(int j = 0; j < FieldSize-len;j++) h[i] = " " + h[i];
             t.append(h[i] + "\t");
          }
          t.append("\n" + "\n");
       }
       
    
       public void setFormat(String pattern[],int FieldSize) {
          this.FieldSize = FieldSize;
          for(int i = 0; i < n ; i++)
            number[i] = new DecimalFormat(pattern[i]);
       }
       
       public void println(String S) {
          t.append(S + "\n");
        }
    
        public void addEntries() {
          int len;
          String s;
          setFont(new Font("Monospaced",Font.PLAIN,10));
          for(int i = 0; i < n ; i++) {
             s = number[i].format(entry[i]);
             len = s.length();
             if(len < FieldSize) 
                for(int j = 0; j < FieldSize-len;j++) s = " " + s;
             t.append(s + "\t");
          }
          t.append("\n");
       }
      
        public void setEntry(int i, double x) {
           entry[i] = x;
        }
    
        public void setEntry(double x0, double x1) {
           entry[0] = x0;
           entry[1] = x1;
        }
    
        public void setEntry(double x0, double x1, double x2) {
           entry[0] = x0;
           entry[1] = x1;
           entry[2] = x2;
        }
    
        public void setEntry(double x0, double x1, double x2, double x3) {
           entry[0] = x0;
           entry[1] = x1;
           entry[2] = x2;
           entry[3] = x3;
        }
    
    }
    
    
    
    package simphy;
    import java.awt.*;
    
         public class Plot extends Frame{
          double scalex,scaley,xmin,ymin,xmax,ymax;
          int nAxes;
          String xLabel,yLabel;
          int mg = 30;
          int xSize,ySize;
          int symbolSize;
          String symbolType;
          Image buffer;
          Graphics b;
          
          public Plot(String title, String xLabel, String yLabel, int nAxes, 
                  double xmin,double xmax, double ymin, double ymax, int symbolSize, String symbolType) {
                  this.nAxes = nAxes;
                  this.xLabel = xLabel;
                  this.yLabel = yLabel;
                  this.xmin = xmin;
                  this.ymin = ymin;
                  this.xmax = xmax;
                  this.ymax = ymax;
                  this.symbolSize = symbolSize;
                  setTitle(title);
                  setSize(400,400);
                  xSize = size().width;
                  ySize = size().height;
                  setLocation(150,150);
                  setVisible(true);
                  setScale();
                  buffer = createImage(getSize().width,getSize().height);
                  b = buffer.getGraphics();
                  setAxes();
          }
           public Plot(String title, String xLabel, String yLabel, int nAxes, 
                  double xmin,double xmax, double ymin, double ymax) {
                  this(title,xLabel,yLabel,nAxes,xmin,xmax,ymin,ymax,1,"dot");
           }
           public Plot(int nAxes, 
                  double xmin,double xmax, double ymin, double ymax) {
                  this("Plot","x","y",nAxes,xmin,xmax,ymin,ymax,1,"dot");
           }
          
           public void paint(Graphics g) {
                g.drawImage(buffer,0,0,this);   // draw image onto screen 
            }
     
              
           private void setScale() { 
                  if(xmax > xmin) 
                     scalex = (size().width-2*mg)/(xmax-xmin);
                  else {
                     System.out.println("Error  xmax not greater than xmin");
                     return;
                  }
                  if(ymax > ymin) 
                     scaley = (size().height-2*mg)/(ymax-ymin);
                  else {
                     System.out.println("Error  ymax not greater than ymin");
                     return;
                  }
            }
            
            
            public void setAxes() {
                   int mg = 30; 
                   int ix,iy;  
                   if(xSize != size().width || ySize != size().height) {
                        xSize = size().width;
                        ySize = size().height;
                        setScale();
                   }
                   b.clearRect(0,0,getSize().width,getSize().height);
                   switch (nAxes) {   // draw axes and axis labels
                    case 1: b.drawLine(mg,size().height-mg,size().width-mg,size().height-mg);
                            b.drawString(xLabel,size().width/2,size().height-10);
                            break;
                    case 2: b.drawLine(mg,size().height-mg,mg,mg);
                            b.drawLine(mg,size().height-mg,size().width-mg,size().height-mg);
                            b.drawString(xLabel,size().width-2*mg,size().height-10);
                            b.drawString(yLabel,10,20);
                            break;
                    case 3: b.drawLine(mg,size().height-mg,size().width-mg,size().height-mg);
                            b.drawLine(size().width/2,size().height-mg,size().width/2,mg);
                            b.drawString(xLabel,size().width-2*mg,size().height-10);
                            b.drawString(yLabel,size().width/2,20);
                            break;
                    case 4: b.drawLine(mg,size().height/2,size().width-mg,size().height/2);
                            b.drawLine(size().width/2,size().height-mg,size().width/2,mg);
                            b.drawString(xLabel,size().width-2*mg,size().height/2+20);
                            b.drawString(yLabel,size().width/2,20);
                            break;
                    case 5: b.drawLine(mg,size().height/2,size().width-mg,size().height/2);
                            b.drawLine(mg,mg,mg,size().height-mg);
                            b.drawString(xLabel,size().width-2*mg,size().height/2+20);
                            b.drawString(yLabel,mg,20);
                            break;
                  }
                  repaint();
                  
             }
            
             
             public void clearPoints() {
                repaint();
             }
             
             public void plotPoints(double x[],double y[]) {
                   int ix,iy;  
                  for(int i = 0; i < x.length; i++) {     // plot points
                      ix = (int)((x[i]-xmin)*scalex) +mg;
                      iy = size().height - (int)((y[i]-ymin)*scaley) - mg;
                      if(symbolSize > 1) {
                        if(symbolType == "fillsquare")
                           b.fillRect(ix-symbolSize/2,iy-symbolSize/2,symbolSize,symbolSize);
                        else if(symbolType == "opensquare")
                           b.drawRect(ix-symbolSize/2,iy-symbolSize/2,symbolSize,symbolSize);
                        else if(symbolType == "opencircle")
                           b.drawOval(ix-symbolSize/2,iy-symbolSize/2,symbolSize,symbolSize);
                        else 
                           b.fillOval(ix-symbolSize/2,iy-symbolSize/2,symbolSize,symbolSize);
                      }
                      else
                        b.drawLine(ix,iy,ix,iy);
                   }
                   repaint();
            }
          }
    
    
    
    package simphy;
    
         /* Creates Frame for drawing on using world coordinates. y increases as you move up, 
            x increases as you move right. Unless otherwise specified methods use world
            coordinates. */
            
         import java.awt.*;
         
         public class WorldGraphics extends Frame {
          double scalex,scaley,xmin,ymin,xmax,ymax;
          Image buffer;
          Graphics b;
          Color c = Color.black; 
          boolean toScreen = true; // draw to screen as well as buffer
          
           public WorldGraphics(String title, 
                  double xmin,double xmax, double ymin, double ymax) {
                  this.xmin = xmin;
                  this.ymin = ymin;
                  this.xmax = xmax;
                  this.ymax = ymax;
                  double f = (ymax-ymin)/(xmax-xmin);
                  setTitle(title);
                  setSize(360,(int)(360*f));
                  setScale();
                  setLocation(250,170);
                  setVisible(true);
                  buffer = createImage(getSize().width,getSize().height);
                  b = buffer.getGraphics();
          }
                
              
           public void setScale() { 
                  if(xmax > xmin) {
                     scalex = (getSize().width)/(xmax-xmin);
                  }
                  else {
                     System.out.println("Error xmax not greater than xmin");
                     return;
                  }
                  if(ymax > ymin) {
                     scaley = (getSize().height)/(ymax-ymin);
                  }
                  else {
                     System.out.println("Error  ymax not greater than ymin");
                     return;
                  }
            }
            
            private int scrX(double x) {
                  return (int)((x-xmin)*scalex);
            }
    
            private int scrY(double y) {
                  return getSize().height - (int)((y-ymin)*scaley);
            }
    
            private int scrDX(double dx) {
                  return (int)(dx*scalex);
            }
    
            private int scrDY(double dy) {
                  return (int)(dy*scaley);
            }
            
            public void setToScreen(boolean toScreen) {
               this.toScreen = toScreen;
            }
            
            public void drawLine(double x1, double y1, double x2, double y2) {
                  b.drawLine(scrX(x1),scrY(y1),scrX(x2),scrY(y2));
                  if (toScreen) repaint();
             }
          
    
            public void fillRect(double x, double y, double dx, double dy) {
                  b.fillRect(scrX(x),scrY(y)-scrDY(dy),scrDX(dx),scrDY(dy));
                  if (toScreen) repaint();
            }   
            
            public void drawRect(double x, double y, double dx, double dy) {
                  b.drawRect(scrX(x),scrY(y)-scrDY(dy),scrDX(dx),scrDY(dy));
                  if (toScreen) repaint();
            }   
            
            public void drawRect(int x, int y, int dx, int dy) {  // uses screen coordinates
                  b.drawRect(x,y,dx,dy);
                  if (toScreen) repaint();
            }   
            
            public void fillRect(int x, int y, int dx, int dy) {  // uses screen coordinates
                  b.fillRect(x,y,dx,dy);
                  if (toScreen) repaint();
            }   
    
            public void fillOval(double x, double y, double dx, double dy) {
                  b.fillOval(scrX(x),scrY(y)-scrDY(dy),scrDX(dx),scrDY(dy));
                  if (toScreen) repaint();
            }   
    
            public void drawOval(double x, double y, double dx, double dy) {
                  b.drawOval(scrX(x),scrY(y)-scrDY(dy),scrDX(dx),scrDY(dy));
                  if (toScreen) repaint();
            }   
            
            public void drawCircle(double x, double y, double r) {
                  b.drawOval(scrX(x)-scrDX(r),scrY(y)-scrDY(r),scrDX(2*r),scrDY(2*r));
                  if (toScreen) repaint();
            }   
          
            public void fillCircle(double x, double y, double r) {
                  b.fillOval(scrX(x)-scrDX(r),scrY(y)-scrDY(r),scrDX(2*r),scrDY(2*r));
                  if (toScreen) repaint();
            }   
    
           public void clearRect(double x, double y, double dx, double dy) {
                  b.clearRect(scrX(x),scrY(y)-scrDY(dy),scrDX(dx),scrDY(dy));
                  if (toScreen) repaint();
           }
           
           public void clearBuffer() {
                  b.clearRect(scrX(xmin),scrY(ymin)-scrDY(ymax-ymin),scrDX(xmax-xmin),scrDY(ymax-ymin));
           }
           
           public void clearLine(double x1, double y1, double x2, double y2) {  // erase line
                Color cSave = c;
                b.setColor(getBackground());
                drawLine(x1,y1,x2,y2);
                b.setColor(cSave);
           }
           
           public void drawString(String s, double x, double y) {
                  b.drawString(s, scrX(x),scrY(y));
                  if (toScreen) repaint();
           }
          
           public void drawString(String s, int x, int y) {  //uses screen coordinates
                  b.drawString(s,x,y);
                  if (toScreen) repaint();
           }
          
          public void setColor(String s) {
                 if(s == "red") c = Color.red;
                 else if(s == "blue") c = Color.blue;
                 else if(s == "black") c = Color.black;
                 else if(s == "green") c = Color.green;
                 else if(s == "yellow") c = Color.yellow;
                 else if(s == "white") c = Color.white;
                 else if(s == "magenta") c = Color.magenta;
                 else if(s == "cyan") c = Color.cyan;
                 else if(s == "orange") c = Color.orange;
                 else if(s == "pink") c = Color.pink;
                 else if(s == "random") c = new Color((int) (Math.random()*255),
                      (int) (Math.random()*255), (int) (Math.random()*255));
                 b.setColor(c);
          }
          
          public void drawBuffer() {
                Graphics g = getGraphics();
                g.drawImage(buffer,0,0,this);   // draw image onto screen, useful for animation 
          }
    
          public void paint(Graphics g) {
                g.drawImage(buffer,0,0,this);   // draw image onto screen 
            }
          }
    
    
    
    
    Summary of some Basic Java Syntax
    ClassName objectName = new ClassName();
    
    ClassName objectName;
    objectName = new ClassName();
    
    double xarray = new double[10];
    double 2dxarray = new double[10][20];
    
    double xarray[];
    xarray = new double[20];
    
    double xarray[] = {1,2,3,4,5};
    
    
    ClassName.staticMethodName();
    objectName.methodName();
    ClassName.staticVariableName;
    objectName.variableName;
    
    
    
    for(int i = 0; i < n; i++) {
    
    }
    
    
    while(i < n) {
    
    }
       
    
    if(a == b) {  // equals
    
    
    }
    
    
    if(a != b) {   // not equals
    
    
    }
    else if (c == d) {
    
    
    }
    else {
    
    
    }
    
    switch(n) {
       case 0:x = 5;y = 7;break;
       case 1:x = 15;break;
       case 2:x = 3;y = 9;break;
       case 3:x = 25;break;
       default: x = 100;
    }