Much of the syntax of Java is the same as C and C++. One big 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. In this tutorial we assume you have some familiarity with
a programming language. Some familiarity with the syntax of C or C++ will also
be useful.
Application | Applet | GUI Application | GUI Applet | |
Events | Animation | File input and output | Ising Model | Templates |
Application
The features of the Java application included in the above program include:
class ExampleApplication{
public static void main( String args[] ) {
double m, a, force;
m = 2.0; // mass in kilograms
a = 4.0; // acceleration in mks units
force = m*a; // force in newtons
System.out.println(force);
}
}
The structure of an applet is slightly different than that of an application.
Below we show the same program, but written as an applet. Applet
Applets are run by web pages. Below we show a simple HTML document which could
be used to run the above applet. Note that before the applet can be run the
program must be translated into byte code which is placed in the file
ExampleApplet.class. The dimensions of the window where the applet will
appear are defined in the web page. The web page also allows the user to
see the source code for the applet.
The main advantage of Java for our purposes is the easy to use graphical user
interface(GUI) that comes with the language and that is platform independent.
The application below shows how to set up your own interface and one way to
input and output your results.
The above application can be rewritten as an applet, as shown below.
The following applet shows you how to deal with a number of other types of
events. After each event occurs, the program clears the window and prints a
message listing the type of event.
The program above is useful for carrying out a calculation, waiting for an
event, and then carrying out another calculation. However, frequently we want
to be able to interrupt a calculation while it is running. For example, we
might have a simulation running and we want to interrupt the simulation to
change a parameter. The following applet shows how to do this within the
context of an animation. It is a simulation of a ball bouncing around in a
box(defined by the window) with no air friction. When the user clicks the
mouse, the ball moves to the position of the mouseclick. The simulation also
allows the user to resize the window, so that the ball reflects off the new
edges of the new window.
The above program includes a number of new features:
At the present time Java is significantly slower than other languages used
for scientific programming. Hopefully, this will change in the future.
For our purposes the main advantage of Java is its interactive nature and the
ease of doing graphics that are platform independent. It is useful to be able
to create data using another language and then be able to read the data in
using Java. The following two programs show how to do file input and output. An
excellent reference for this and other aspects of Java is the book "On to Java"
by Patrick Henry Winston and Sundar Narasimhan(Addison-Wesley, 1996).
Note the following features of the above programs.
Our final example shows an Ising model simulation based on Program
Ising in Chapter 17 of Gould & Tobochnik.
The above program includes most of what one needs to run simulations in physics
with user interaction. The main new features of the program are listed below.
The above programs show the power and ease of use of Java graphics and user
interactions. Below we show three useful classes which can be used as
templates for building programs which really utilize the object oriented power
of Java. We list a template for a Frame. Attached to the Frame are a Panel
where Buttons and TextFields for user interaction with the program are placed.
Also, attached is a Canvas where the drawing can be done and calls to physics
methods are made. Ideally, the user should define other classes which
represent physical objects such as an Ising lattice, a particle moving in
a potential, or a fractal. Also, it is common practive to place each class
declaration in a separate file.
These templates can be used with applets. To do so eliminate the FrameTemplate class,
and replace the GeneralFrame class by a class that extends the Applet class.
The features of the Java applet that are different than the application are:
import java.awt.*;
import java.applet.Applet;
public class ExampleApplet extends Applet{
public void paint( Graphics g ) {
double m, a, force;
m = 2.0; // mass in kilograms
a = 4.0; // acceleration in mks units
force = m*a; // force in newtons
g.drawString(String.valueOf(force), 30, 30 );
}
}
<HTML>
<HEAD>
<TITLE>Example Applet</TITLE>
</HEAD>
<HR>
<BODY
<APPLET code="ExampleApplet.class" width=200 height=200>
</APPLET>
<hr>
<a href="ExampleApplet.java">The source.</a>
</BODY>
</HTML>
The features of the Java application included in the above program include:
import java.awt.*;
class GuiApplication {
public static void main( String args[] ) {
MyFrame frame = new MyFrame();
frame.setTitle("Input Example");
frame.resize(500,300);
frame.init();
frame.show();
}
}
class MyFrame extends Frame {
double m = 0; // mass
TextField mText,fText; // textfield to enter mass and output force
Label mLabel, fLabel; // label for mass and force textfield
public void init() {
setLayout(null); // don't use deffault layout
setBackground (Color.lightGray);
mText = new TextField(""); // field to enter mass value
mText.reshape(20,20,50,20); // locate at 20,20; 50 pixels wide and 20 pixels high
add(mText); // add field to window
mLabel = new Label("mass");
mLabel.reshape(20,40,50,20); //locate label below textfield
add(mLabel); //add label to window
fText = new TextField(""); // field to output force value
fText.reshape(80,20,50,20); // locate at 80,20; 50 pixels wide and 20 pixels high
add(fText); // add field to window
fLabel = new Label("force");
fLabel.reshape(80,40,50,20); //locate label below textfield
add(fLabel); //add label to window
}
public void product() {
double a = 5.0,force;
force = m*a; // m is found from handle event routine below
fText.setText(String.valueOf(force));
}
public boolean handleEvent(Event e) {
Rectangle mRect = mText.bounds(); // boundary of mass textfield
if ((e.x == mRect.x) && (e.y == mRect.y)) // text entered in mass textfield
{
Double M = new Double(mText.getText ()); // convert string to Double object
m = M.doubleValue(); // get value of mass from Double object
product();
return (true);
}
else if (e.id == Event.WINDOW_DESTROY) // only needed for application
{
System.exit(0);
return(true);
}
return super.handleEvent(e); // take care of all other events
}
}
import java.awt.*;
import java.applet.*;
public class GuiApplet extends Applet{
double m = 0; // mass
TextField mText,fText; // textfield to enter mass and output force
Label mLabel, fLabel; // label for mass and force textfield
public void init(){
setLayout(null); // don't use deffault layout
setBackground (Color.lightGray);
mText = new TextField(""); // field to enter mass value
mText.reshape(20,20,50,20); // locate at 20,20; 50 pixels wide and 20 pixels high
add(mText); // add field to window
mLabel = new Label("mass");
mLabel.reshape(20,40,50,20); //locate label below textfield
add(mLabel); //add label to window
fText = new TextField(""); // field to output force value
fText.reshape(80,20,50,20); // locate at 80,20; 50 pixels wide and 20 pixels high
add(fText); // add field to window
fLabel = new Label("force");
fLabel.reshape(80,40,50,20); //locate label below textfield
add(fLabel); //add label to window
}
public void product() {
double a = 5.0,force;
force = m*a; // m is found from handle event routine below
fText.setText(String.valueOf(force));
}
public boolean handleEvent(Event e) {
Rectangle mRect = mText.bounds(); // boundary of mass textfield
if ((e.x == mRect.x) && (e.y == mRect.y)) // text entered in mass textfield
{
Double M = new Double(mText.getText ()); // convert string to Double object
m = M.doubleValue(); // get value of mass from Double object
product();
return (true);
}
return super.handleEvent(e); // take care of all other events
}
}
import java.applet.Applet;
import java.awt.*;
import java.util.*;
public class HandleApplet extends Applet{
int xMouse, yMouse; // Current position of the mouse.
int xWindow, yWindow; // Window width and height.
String sMessage = " ";
public void init (){
xMouse = 0;
yMouse = 0;
xWindow = size().width;
yWindow = size().height;
setBackground (Color.lightGray);
}
public boolean handleEvent(Event evt){
if (evt.id == Event.MOUSE_DOWN)
{
sMessage = "Mouse Down";
xMouse = evt.x;
yMouse = evt.y;
repaint ();
return(true);
}
else if (evt.id == Event.MOUSE_UP)
{
sMessage = "Mouse Up";
xMouse = evt.x;
yMouse = evt.y;
repaint ();
return(true);
}
else if (evt.id == Event.MOUSE_MOVE)
{
sMessage = "Mouse Move";
xMouse = evt.x;
yMouse = evt.y;
repaint ();
return(true);
}
else if (evt.id == Event.MOUSE_DRAG)
{
sMessage = "Mouse Drag";
xMouse = evt.x;
yMouse = evt.y;
repaint ();
return(true);
}
else if (evt.id == Event.KEY_PRESS)
{
sMessage = "Key Pressed";
repaint ();
return(true);
}
else if (evt.id == Event.KEY_ACTION)
{
sMessage = "Hot Key Pressed";
repaint ();
return(true);
}
return (super.handleEvent(evt));
}
public void paint (Graphics g){
g.clearRect (0, 0, xWindow, yWindow);
g.drawString (sMessage, xMouse, yMouse);
}
}
import java.awt.*; import java.applet.*;
public class fall extends Applet implements Runnable
{
Thread runner;
int x,y; // ball location
Image buffer;
int curw,curh; // window width and height
int accel = 4,vx,vy;
int bsize = 20; //ball size in pixels
int bsize1 = bsize + 1;
public void init() {
x = y = bsize; //initial conditions
vx = 6;
vy = 0;
}
public void start() {
runner = new Thread(this);
runner.start();
}
public void stop() {
runner.stop();
}
public void run() {
while (true) {
if ((buffer == null) || ( curw!= size().width) || (curh!= size().height))
{
buffer = createImage(size().width, size().height); // create graphics buffer
curw = size().width;
curh = size().height;
}
Rectangle oldRect = new Rectangle(x,y,bsize1,bsize1);
x += vx;
y += vy + 0.5*accel; // midpoint algorithm which is exact for constant acceleration
vy += accel;
Rectangle newRect = new Rectangle(x,y,bsize1,bsize1);
Rectangle r = newRect.union(oldRect);
Graphics g = buffer.getGraphics();
g.clipRect(r.x,r.y,r.width,r.height);
update(g);
g = getGraphics();
g.clipRect(r.x,r.y,r.width,r.height);
g.drawImage(buffer,0,0,this);
if (x <= 0 && vx < 0)
vx = -vx;
else if (x + bsize >= size().width && vx > 0)
vx = -vx;
if (y <= 0 && vy < 0)
vy = -vy;
else if (y + bsize >= size().height && vy > 0)
vy = -vy;
try {Thread.sleep(25);} // delay 25 msec between updates
catch (InterruptedException e){};
}
}
public boolean handleEvent(Event evt){
if (evt.id == Event.MOUSE_DOWN)
{
Graphics g = getGraphics();
g.clearRect (0, 0, size().width, size().height); // clear window
x = evt.x;
y = evt.y;
repaint(); // redraw window
return(true);
}
return (super.handleEvent(evt));
}
public void paint( Graphics g ) {
g.setColor(Color.red);
g.fillOval(x,y,bsize,bsize);
g.setColor(Color.blue);
g.drawString("Free Fall in a box",30,10); // title
}
}
/*
Application that inputs numbers from a text file -
reference page 135-143 in Onto Java */
import java.io.*;
public class TokensIn {
public static void main(String args[]) throws IOException{
double x;
String s;
FileInputStream fis = new FileInputStream("abc.in"); // associate input stream to file
StreamTokenizer tokens = new StreamTokenizer(fis); // divide input stream into tokens
int next = 0;
// set next equal to next token and check for end of file.
while ((next = tokens.nextToken()) != tokens.TT_EOF) {
if(next == tokens.TT_WORD){
s = tokens.sval; // set s equal to string value of token
System.out.println(s); }
else {
x = tokens.nval; // set x equal to numeric value of token
System.out.println(x); } }
fis.close();
}
}
/*
Application that outputs numbers to a text file - reference page 181-183 in On to Java
*/
import java.io.*;
public class TokensOut {
public static void main(String args[]) throws IOException{
double x;
FileOutputStream fos = new FileOutputStream("abc.out"); // associate output stream to file
PrintStream output = new PrintStream(fos); // divide input stream into tokens
for(int k = 0;k < 10; k++) {
x = k*5.1; // set x equal to value of token
output.print(x);
output.print('\t'); // add tab between data, useful for using cricket graph
output.println(2*x); } // carriage return after printing x
fos.close();
}
}
import java.applet.*;
import java.awt.*;
import java.util.*;
public class isingApplet extends Applet implements Runnable
/***************************************************************************
2-d Ising Model simulation - Java version of Program Ising, page 575
of An Intorduction to Computer Simulation Methods by Harvey Gould and
Jan Tobochnik, Addison-Wesley, 1996.
***************************************************************************/
{
int L = 20; // dimension of lattice
int N = L*L; // number of spins
int spin[][] = new int[L][L]; // array of walker coordinates
double w[] = new double[10]; // Boltzmann weigts
int t = 0; // time in MCS per spin
double T = 2.269; // initial temperature = Tc
Button bhot,bcold,bstop,bcont;
Thread runner;
boolean running = false; // true if simulation is running
Scrollbar sTemp;
TextField tTemp,tTime;
TextField tMag,tChi,tEner,tSH,tAccept;
Label lTemp;
int x,y; // current spin coordinates
int shift=100; // x and y location of lattice corner
int wcell = 5; // cell width
double M = 0,M2 = 0,E = 0,E2 = 0;
double Accept;
/***************************************************************************/
public void init (){
// set up window with buttons, textfields and scrollbar
setLayout(null);
setBackground (Color.lightGray);
tTime = new TextField ("t = " + String.valueOf(t));
tTime.reshape(10,10,50,20);
add(tTime);
bhot = new Button("start hot"); // add buttons
bhot.reshape(40,50,80,20);
add(bhot);
bcold = new Button("start cold");
bcold.reshape(140,50,80,20);
add(bcold);
bstop = new Button("stop");
bstop.reshape(240,50,80,20);
add(bstop);
bcont = new Button("continue");
bcont.reshape(340,50,80,20);
add(bcont);
lTemp = new Label("Temperature"); // Temperature Label
lTemp.reshape(200,10,100,20);
add(lTemp);
// Temperature Scrollbar
sTemp = new Scrollbar (Scrollbar.HORIZONTAL,(int) (100.0*T),5,0,500);
sTemp.reshape(280,10,100,20);
add(sTemp);
tTemp = new TextField (String.valueOf(T)); // Temperture Textfield
tTemp.reshape(400,10,50,20);
add(tTemp);
boltzmann();
// Textfields for output of averages
tMag = new TextField ("M/N = ");
tMag.reshape(10,230,150,20);
add(tMag);
tChi = new TextField ("Susc = ");
tChi.reshape(10,260,150,20);
add(tChi);
tEner = new TextField ("E/N = ");
tEner.reshape(190,230,150,20);
add(tEner);
tSH = new TextField ("C = ");
tSH.reshape(190,260,150,20);
add(tSH);
tAccept = new TextField ("Acceptance Ratio = ");
tAccept.reshape(370,230,100,30);
add(tAccept);
}
public void start(){ // start thread
runner = new Thread(this);
runner.start();
}
public void stop(){ // stop thread
runner.stop();
}
public void run(){ // run thread
while(true)
{
if (running) // check to see if stop button pushed
{
MonteCarlo();
averages();
} //end if
try {Thread.sleep(250);} // check for events
catch (InterruptedException e){};
} //end while
}
public void MonteCarlo(){
int dE;
for (int i = 1;i <= N;i++) // Begin Monte Carlo code
{
x = (int) (L*Math.random()); // random number between 0 and L-1
y = (int) (L*Math.random());
dE = spin[x][y]*(spin[pbc(x-1)][y] + spin[pbc(x+1)][y]
+ spin[x][pbc(y-1)] + spin[x][pbc(y+1)]);
if(w[dE+4] > Math.random())
{
spin[x][y] = -spin[x][y]; // accept flip
drawSpin();
Accept++;
}
}
t++; // increment time
}
public void drawSpin() // draw spins
{
Graphics g = getGraphics();
if(spin[x][y] == 1)
g.setColor(Color.red);
else
g.setColor(Color.blue);
g.fillRect(shift+x*wcell,shift+y*wcell,wcell,wcell);
g.dispose();
}
public void averages()
{
double m=0,e=0,SH,Chi;
for(int i=0;i < L; i++)
for(int j=0;j < L; j++)
{
m += spin[i][j];
e -= spin[i][j]*(spin[i][pbc(j+1)] + spin[pbc(i+1)][j]);
}
M += m;
M2 += m*m;
E += e;
E2 += e*e;
Chi = (1.0/(T*N))*((M2/t) - (M/t)*(M/t));
SH = (1.0/(T*T*N))*((E2/t) - (E/t)*(E/t));
// Print averages
tTime.setText("t = " + String.valueOf(t));
tMag.setText("Mag/N = " + String.valueOf(M/(t*N)).substring(0,5));
tChi.setText("Susc. = " + String.valueOf(Chi));
tEner.setText("E/N = " + String.valueOf(E/(t*N)));
tSH.setText("C = " + String.valueOf(SH));
tAccept.setText("Acceptance Ratio = " + String.valueOf(Accept/(t*N)));
}
public int pbc(int s) { // periodic boundary conditions
if(s == -1)
return(L-1);
else if(s == L)
return(0);
else
return(s);
}
public void boltzmann(){
for(int i=-4;i <= 4; i++)
w[i+4] = Math.exp(-2.0*i/T);
}
public boolean handleEvent(Event evt){
if (evt.id == Event.ACTION_EVENT)
return action(evt,evt.arg);
return (super.handleEvent(evt)); }
public boolean action(Event evt, Object arg)
{
if ( evt.target == bcont) // continue
{
running = true;
return(true);
}//end if
else if ( evt.target == bhot) // start hot
{
for (x = 0;x < L;x++)
for (y = 0;y < L;y++)
{
if(Math.random() > 0.5)
spin[x][y] = 1;
else
spin[x][y] = -1;
drawSpin();
}
running = true;
return(true);
}//end if
else if ( evt.target == bcold) // start cold
{
for (x = 0;x < L;x++)
for (y = 0;y < L;y++)
{
spin[x][y] = -1;
drawSpin();
}
running = true;
return(true);
}//end if
else if ( evt.target == bstop) // stop
{
running = false;
return(true);
}//end if
else if ((evt.id == Event.SCROLL_ABSOLUTE) || (evt.id == Event.SCROLL_LINE_UP)
|| (evt.id == Event.SCROLL_LINE_DOWN) || (evt.id == Event.SCROLL_PAGE_UP)
|| (evt.id == Event.SCROLL_PAGE_DOWN) )
{
T = (double) ((((Integer) evt.arg).intValue())/100.0);
tTemp.setText(String.valueOf(T));
t = 0;
M = M2 = E = E2 = Accept = 0;
boltzmann();
return(true);
}
else if ( evt.target == tTemp) // stop
{
Double Td = new Double(tTemp.getText());
T = Td.doubleValue();
sTemp.setValue( (int) (T*100));
t = 0;
M = M2 = E = E2 = Accept = 0;
boltzmann();
return(true);
}//end if
return false;
}
}
/* This template sets up a window frame and adds a panel of TextFields and Buttons and a
canvas for drawing. The necessary changes for the user to make are to put in appropriate labels
for the TextFields and Buttons in the init() method. There can be any number of TextFields
and Buttons. The number of labels should match the number of TextFields. Most of the programming
effort is in creating the canvas */
import java.awt.*;
class FrameTemplate {
public static void main(String args[]) {
GeneralFrame frm = new GeneralFrame(); // set up window for application
frm.setTitle("Project Title");
frm.resize(500,300);
frm.init();
frm.show();
frm.start(); } } // end FrameTemplate
class GeneralFrame extends Frame implements Runnable {
sipPanel thisPanel;
CanvasTemplate thisCanvas;
Thread runner;
public void init() {
String lstring[] = {"label 1", "label 2"}; // change and add labels for TextFields
String tstring[] = {String.valueOf(1),String.valueOf(1)}; // change and add values
String bstring[] = {"label 1 ", "label 2", "label 3"}; // change and add labels for Buttons
setLayout(new BorderLayout());
thisPanel = new sipPanel(lstring,tstring,bstring); // panel for Buttons and TextFields
add("North",thisPanel);
thisCanvas = new CanvasTemplate(); // Canvas for drawing and physics
add("Center", thisCanvas); }
public void start() {
runner = new Thread(this);
runner.start(); }
public void stop() {
runner.stop(); }
public void run() {
while(true) {
try {Thread.sleep(1000);} // delay 1000 msec between updates
catch (InterruptedException e){}; } }
public boolean handleEvent(Event evt){
if (evt.id == Event.ACTION_EVENT)
return action(evt,evt.arg);
return (super.handleEvent(evt)); }
public boolean action(Event evt, Object arg){
for(int i = 0; i < thisPanel.buttons.length;i++)
if (evt.target == thisPanel.buttons[i]) { // button pushed
thisCanvas.buttonAction(i);
return(true); }
for(int i = 0; i < thisPanel.texts.length;i++)
if (evt.target == thisPanel.texts[i]) { // TextField changed
Double R = new Double(thisPanel.texts[i].getText());
thisCanvas.textAction(i,R.doubleValue());
return(true); }
return false; } }
/* The following class requires no modification from the user */
import java.awt.*;
class sipPanel extends Panel {
TextField texts[];
Label labels[];
Button buttons[];
public sipPanel(String lstring[], String tstring[], String bstring[] ) {
setLayout(new FlowLayout());
int nT = lstring.length;
int nB = bstring.length;
texts = new TextField[nT];
labels = new Label[nT];
buttons = new Button[nB];
for(int i = 0; i < nT;i++) {
labels[i]= new Label(lstring[i]);
add(labels[i]);
texts[i]= new TextField(tstring[i]);
add(texts[i]); }
for(int i = 0; i < nB;i++) {
buttons[i] = new Button(bstring[i]);
add(buttons[i]); } } }
/* Below are the methods that must be defined so that CanvasTemplate will work with
FrameTemplate and sipPanel. Each method in buttonAction must be written and
each variable in textAction must be declared. Other methods for drawing and
doing physics must be written as well. */
import java.awt.*;
class CanvasTemplate extends Canvas{
/* Place object and variable declarations used by more than one method
or by other classes here */
public CanvasTemplate() {
// Constructor. Place here code to be executed whenever new object created
}
public void buttonAction(int i) {
switch(i) {
case 0: method0(); break; // method to be executed when button 0 pushed
case 1: method1(); break;
case 2: method2(); } }
public void textAction(int i, double value) {
switch(i) {
case 0: N0 = (int) value; break; // convert to an integer
case 1: N1 = value; } } } // leave as a double