/** * Iterated Difference Equation Demonstrator Applet * @author Robert J Morton UK-YE572246C * @version 27 November 1997 modified 07 August 2009, 18 April 2012 */ /* Iterates the two difference equations x = cx(1 - x) and x = x**2 + c according to which one the user selects on the control panel. Provides real-time Time Line and Bounce graphs so the user can see the equations being iterated. This applet employs separate dedicated TimeGr and BounceGr classes to implement real-time graph plotting. Its control panel is provided by a dedicated CtrlPanl class which is a container for separate dedicated classes SelPer to select the iteration period, SelEqn to select the desired equation to iterate, SelScan for selecting between single-scan mode continuous scanning mode, SetCval to provide a text entry field for the constant c in the equations, IncCval provides + - buttons to increment/decrement c by 0.1 per hit, and SetButt which contains Start/Stop and Reset buttons. There is also a class SelPlot which allows you to select between having the Time Graph plot by joining successive plots with straight lines or having it mark each spot value of x with a short horizontal line equal in length to one time period. */ import java.awt.*; // java graphical interface import java.applet.*; // all the gubbins to make the applet work import javax.swing.*; // library for constructing Swing GUI public class difeqnap extends JApplet implements Runnable { private static final Color bc = new Color(245,245,240), // panels background colour BC = new Color(238,238,238); // applet background colour private boolean RunFlag=false, // applet starts with no equation iterating INIT=true, // in-loop initialisation not yet done AutoStart=true; // auto-start required private int delay=20; // initial three-second delay before autostart private long Period=100, // inter-plot time frame (milliseconds) 100ms T; // system time at which a new plot is due to begin private Image TG = null, // reference for a Time Graph image object BG = null; // reference for a Bounce Graph image object private formula f; // instance reference to the formula class private timegr tg; // reference for a Time Graph object private bouncegr bg; // reference for a Bounce Graph object private setbutt sb; // instance reference to the setbutt class private Thread Iter; // thread reference variable for this program private Font font = new Font("Sans",Font.BOLD,12); private FontMetrics fm; // dimensions of the above font public void init(){ // INITIALISE THE APPLET try { // Attempt Phase 1 of GUI construction process javax.swing.SwingUtilities.invokeAndWait( new Runnable() { public void run(){ init1(); } } ); } catch(Exception e) { showStatus("couldn't create Swing GUI"); } Iter=new Thread(this); // Create a program thread object and start it // system time at end of first plot's iteration period T=System.currentTimeMillis() + Period; } /* THE FIRST PHASE OF INITIALISATION. Since this involves the creation and set-up of Swing widgets, it must be done on the Event Dispatching thread. It is invoked from the applet's init() method above. */ private void init1() { /* Get the reference to the content pane of this JApplet and set the pane layout mode so that objects can be arranged on it manually. */ Container cp = getContentPane(); cp.setLayout(null); f = new formula(this); // create an instance of the formula class /* Create two image objects on which to draw the Time Graph and Bounce Graph axes, and get their respective graphics contexts. */ TG=createImage(545,180); Graphics ga=TG.getGraphics(); BG=createImage(185,185); Graphics gb=BG.getGraphics(); /* Create a Bounce Graph panel, add it to the applet's pane, morph it to fit into the bottom right corner of applet window and set the background colour of the control panel. */ bg = new bouncegr(bc,f,gb,BG,font); cp.add(bg); bg.setBounds(360,180,185,185); bg.setBackground(bc); /* Create a Time Graph panel, add it to the applet's pane, morph it to fit into the to part of applet window and set the background colour of the control panel. */ tg = new timegr(this,bc,f,ga,font,TG); cp.add(tg); tg.setBounds(0,0,545,180); tg.setBackground(bc); f.setBG(bg); // pass instance ref of bounce graph to formula class /* Create the Control Panel, add it to the applet's pane, morph it to fit into the botton left part of applet window and set the background colour of the control panel. */ ctrlpanl CP=new ctrlpanl(this,tg,bg,f); cp.add(CP); CP.setBounds(0,180,360,185); CP.setBackground(bc); } void setSB(setbutt sb) {this.sb=sb;} // instance reference to button panel void setPeriod(long p) {Period=p;} // set the formula iteration period void setRF(boolean b) {RunFlag=b;} // set the Run() state // Starts the program thread by requesting a call to run() public void start(){ Iter.start(); } public void run(){ // run the Track Recorder painting thread while(true){ // permanent loop runLoop(); // see below /* Get time left in this plot's time frame making sure it can't be less than 5 milliseconds then put the thread to sleep for this remaining time. */ long s=T-System.currentTimeMillis(); if(s < 5) s = 5; try{Thread.currentThread().sleep(s); } /* Catch any exceptions during this sleep but do nothing about them because they are normal events. from the GUI. Afterwards, set the system time at which next plot's time-frame will finish. */ catch(InterruptedException e){} T=System.currentTimeMillis()+Period; } } /* The delays in the initialisation sections of the following loop are necessary to allow Swing time to initialise its widgets. Setting a 'ready' flag in the init() or init1() methods doesn't work. This strikes me as a very poor situation. Swing should provide some definitive signal that it has finished building the widgets. */ private void runLoop() { if(INIT){ // if in-loop initialisation has not yet been done /* If the decremented delay has expired, initialise the bounce and time graphs, reinitialise the delay and signal that the initialisation pass has been done. */ if(delay-- < 0){ bg.reset(); tg.reset(); delay=20; INIT=false; } return; // bail out of the run() loop } if(AutoStart){ // if not yet automatically started /* If decremented delay has expired, hit the 'Start' button and signal that auto start has occurred. */ if(delay-- < 0){ sb.whichButton(0); AutoStart=false; } return; // bail out of the run() loop } /* If the iteration process is running, update the value of 'x' and paint next plot on the bounceand time graphs. */ if(RunFlag) { f.iterate(); bg.Plot(); tg.Plot(); } } public void stop(){Iter=null;} // Stop this a program thread /* shut down and discard this applet: if its thread is still running (which it shouldn't be), disembody it from its reference so it gets garbaged. */ public void destroy(){ if(Iter != null) Iter = null; } }