// "Java Tech"
// Code provided with book for educational purposes only.
// No warranty or guarantee implied.
// This code freely available. No copyright claimed.
// 2003
//
// Begun from StartJApplet 11
// Include the tag here for testing with the Appletviewer
/*
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
* This program will run as an applet inside
* an application frame.<
*
* The applet uses DropPanel to simulate the dropping of a
* mass in a constant gravitational field. A HistPanel displays
* a histogram of the measurements of the acceleration. PlotFormat
* is used by HistPanel to format the scale values.
*
* The java.util.Timer and java.util.TimerTask are used
* to update the animation of the drop.
*
* Includes "Drop" button to initiate the dropping.
*
* The number of values taken from
* entry in a JTextField. "Clear" button clears the histogram.
* In standalone mode, the Exit button closes the program.
*
*
**/
public class DropTestApplet extends JApplet
implements ActionListener
{
// The DropPanel displays the animation of the
// falling mass.
DropPanel fDropPanel;
// The DropModel generates the physics data.
DropModel fDropModel;
// Use the HistPanel JPanel subclass here
HistPanel fHistPanel;
Histogram fHistogram;
int fNumDataPoints = 100;
boolean fMakingHist = false;
boolean fUpdateDisplay = false;
// Use the java.util Timer and TimerTask combo
// for timing events.
java.util.Timer fTimer;
// A text field for getting number of drops per
// run and the time factor
JTextField fMaxNumDropsField;
JTextField fTFactorField;
// Flag for whether the applet is in a browser
// or running via the main () below.
boolean fInBrowser = true;
//Buttons
JButton fGoButton; // start drop
JButton fClearButton;// resets histogram
JButton fExitButton;
// The bottom coordinate of the drop tower
double fYBottom = 0;
// Starting coordinates of drop
double fXBallStart = 25.0; // cm
double fYBallStart = 200.0; // cm
// Initial velocity.
double fVyBallStart = 0.0;
double fVxBallStart = 0.0;
// Coordinate of ball.
double fXBall;
double fYBall;
// Time in millisecs when the last drop step made
double fTDropTotal;
// Speed up or slow down factor for animation:
double fTFactor = 1.0;
double fTFrame = 0.020; // in secs
// Allow for multiple drops per "run"
int fMaxNumDrops = 1;
int fNumDrops = 0;
/**
* Create a User Interface with a textarea with sroll bars
* and a Go button to initiate processing and a Clear button
* to clear the textarea.
**/
public void init () {
JPanel panel = new JPanel (new BorderLayout ());
// Use a textfield to get the number of drops per run.
fMaxNumDropsField =
new JTextField (Integer.toString (fMaxNumDrops), 10);
// Use a textfield to get the number of drops per run.
fTFactorField =
new JTextField (Double.toString (fTFactor), 10);
// If return hit after entering text, the
// actionPerformed will be invoked.
fMaxNumDropsField.addActionListener (this);
fTFactorField.addActionListener (this);
fGoButton = new JButton ("Drop");
fGoButton.addActionListener (this);
// Here the clear button will reset the histogram
fClearButton = new JButton ("Reset");
fClearButton.addActionListener (this);
fExitButton = new JButton ("Exit");
fExitButton.addActionListener (this);
JPanel controlPanel = new JPanel (new GridLayout (1,2));
JPanel panel1 = new JPanel (new GridLayout (1,2));
JPanel panel2 = new JPanel (new GridLayout (1,3));
panel1.add (fMaxNumDropsField);
panel1.add (fTFactorField);
panel2.add (fGoButton);
panel2.add (fClearButton);
panel2.add (fExitButton);
controlPanel.add (panel1);
controlPanel.add (panel2);
// Create an instance of the DropPanel
fDropPanel = new DropPanel (fYBallStart, 0.0);
// Create a histogram to plot the variance in the
// drop times.
fHistogram = new Histogram ("Delta Time","Data", 20,0.0,1.0);
fHistPanel = new HistPanel (fHistogram);
JPanel holder_panel = new JPanel (new GridLayout (1,2));
holder_panel.add (fDropPanel);
holder_panel.add (fHistPanel);
panel.add (holder_panel,"Center");
panel.add (controlPanel,"South");
// Add text area with scrolling to the content pane.
add (panel);
// Create the drop physics model
fDropModel = new DropModel ();
fDropModel.setParams (fYBallStart, fVyBallStart);
} // init
/** Stop the timer if the browser page unloaded. */
public void stop () {
runDone ();
} // stop
/** Respond to the buttons. */
public void actionPerformed (ActionEvent e) {
Object source = e.getSource ();
if (source == fGoButton) {
if (fGoButton.getText ().equals ("Drop")) {
try {
fMaxNumDrops =
Integer.parseInt (fMaxNumDropsField.getText ());
fTFactor =
Double.parseDouble (fTFactorField.getText ());
}
catch (NumberFormatException ex) {
// Could open an error dialog here but just
// display a message on the browser status line.
showStatus ("Bad input value");
return;
}
dropReset ();
fGoButton.setText ("Stop");
fClearButton.setEnabled (false);
} else {
dropDone ();
}
}
else if (source == fClearButton) {
runReset();
} else if (!fInBrowser)
System.exit (0);
} // actionPerformed
/**
* Before each set of drops, need to create a new timer,
* and set up its schedule. The PaintHistTask innner class
* object will do the setup for each frame of a drop animation.
**/
void dropReset () {
// Before starting the drop, create the timer task
// that will cause the histogram display to update
// during the filling.
// Create a timer. TimerTask created in MakeHist ()
fTimer = new java.util.Timer ();
fDropPanel.reset (fXBallStart, fYBallStart);
fDropModel.setParams (fYBallStart, fVyBallStart);
// Start the timer after 20ms and then repeat calls
// to run in PaintHistTask object by the rate set by
// the fTFrame value.
fTimer.schedule (new PaintHistTask (), 20, (int)(fTFrame*1000));
// Reset time sum
fTDropTotal = 0.0;
fNumDrops = 0;
fYBall = fYBallStart;
fXBall = fXBallStart;
} // dropReset
/**
* Use the inner class technique to define the
* TimerTask subclass for stepping through the
* drop calculation and the frame refresh.
* Use the real time in the drop calculation instead
* of the given frame rate times in case there were
* delays from thread interruptions, the processing
* in the parts of the program take extra time, etc.
**/
class PaintHistTask extends java.util.TimerTask {
public void run () {
// Drop the ball
fYBall = fDropModel.step (fTFactor * fTFrame);
// Update the position of the ball in the
// animation and redraw the frame.
fDropPanel.updatePosition (fXBall, fYBall);
// Save the time.
fTDropTotal += fTFactor * fTFrame;
// Check if ball has crossed the finish line.
if (fYBall <= fYBottom) dropDone ();
} // run
} // PaintHistTask
/**
* Invoked when all the drops are done. Reset
* all the parameters to set up for another drop.
**/
public void dropDone () {
// Add time for this drop. Remove the time factor.
fHistogram.add (fTDropTotal);
++fNumDrops;
// Check if all drops completed.
if (fNumDrops == fMaxNumDrops){
// If so then finish up the data recording
// for this run and return.
runDone ();
return;
}
// Reset time sum
fTDropTotal = 0.0;
fYBall = fYBallStart;
fXBall = fXBallStart;
fDropPanel.reset (fXBallStart, fYBallStart);
fDropModel.setParams (fYBallStart, fVyBallStart);
} // dropDone
/** Invoked when Clear button selected. **/
public void runReset () {
// Clear the histogram
fHistogram.clear ();
// Reset time sum
fTDropTotal = 0.0;
fYBall = fYBallStart;
fXBall = fXBallStart;
fDropPanel.reset (fXBallStart, fYBallStart);
fDropModel.setParams (fYBallStart, fVyBallStart);
repaint();
} // runReset
/**
* Invoked when all the drops are done. Kill the timer.
* A new timer must be created for each run.
* Display the histogram with the additional data.
**/
public void runDone (){
// Stop the animation.
fTimer.cancel ();
// Update histogram
fHistPanel.repaint ();
// Reset the buttons.
fGoButton.setText ("Drop");
fClearButton.setEnabled (true);
} // runDone
/** Offer the option of running the applet in an app frame. */
public static void main (String[] args) {
//
int frame_width=450;
int frame_height=300;
//
DropTestApplet applet = new DropTestApplet ();
applet.fInBrowser = false;
applet.init ();
// Following anonymous class used to close window & exit program
JFrame f = new JFrame ("Drop Test");
f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
// Add applet to the frame
f.getContentPane ().add ( applet);
f.setSize (new Dimension (frame_width,frame_height));
f.setVisible (true);
} // main
} // DropTestApplet