// "Java Tech"
// Code provided with book for educational purposes only.
// No warranty or guarantee implied.
// This code freely available. No copyright claimed.
// 2003
//
// Begun with StartJApplet11
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
/**
* This applet/application uses StreamedHistPanels to display the contents
* of 3 Histograms to show distributions of sensor data. The basic form
* of the class goes as TimerHistFill_JApplet11. However, data is sent to
* the StreamedHistPanels as OutputStreams.
*
* Data is generated from an instance of MakeSensorData in a thread
* to simulate the input of data events at random times. The three
* sensors each produce a Gaussian distribution of values but they
* are transformed by different slopes and offsets (or pedestals)
* to represent variations in the sensor hardware.
**/
public class HistStreamApplet extends JApplet
implements ActionListener, Updateable
{
final static int NUM_HISTS = 3;
// Histograms for the panels.
Histogram [] fHistogram = new Histogram[NUM_HISTS];
// The HistPanel subclass that accept data streams.
StreamedHistPanel [] fHistPanel = new StreamedHistPanel[NUM_HISTS];
// Create a panel to hold the histogram sub-panels
JPanel fHistsPanel = null;
// Array of treams to the panels
OutputStream [] fDataOut = new OutputStream[NUM_HISTS];
// Constants for three channels of sensor data.
double [] fSlope = {0.6, 1.2, 1.1};
double [] fPedestal = {2.4, 1.3, 3.4};
int fNumDataPoints = 100;
boolean fMakingHist = false;
boolean fUpdateDisplay = false;
MakeSensorData fMakeData = null;
// Use the java.util Timer and TimerTask combo
// for timing events.
java.util.Timer fTimer = null;
// A text field for input strings
JTextField fTextField = null;
// Flag for whether the applet is in a browser
// or running via the main () below.
boolean fInBrowser=true;
//Buttons
JButton fGoButton = null;
JButton fClearButton = null;
JButton fExitButton = null;
public void init () {
Container content_pane = getContentPane ();
JPanel panel = new JPanel (new BorderLayout ());
// Use a textfield for an input parameter.
fTextField =
new JTextField (Integer.toString (fNumDataPoints), 10);
// If return hit after entering text, the
// actionPerformed will be invoked.
fTextField.addActionListener (this);
fGoButton = new JButton ("Go");
fGoButton.addActionListener (this);
fClearButton = new JButton ("Clear");
fClearButton.addActionListener (this);
fExitButton = new JButton ("Exit");
fExitButton.addActionListener (this);
JPanel control_panel = new JPanel ();
control_panel.add (fTextField);
control_panel.add (fGoButton);
control_panel.add (fClearButton);
control_panel.add (fExitButton);
// Create a panel to hold the histogram sub-panels
fHistsPanel = new JPanel (new GridLayout (1,3));
// Create the HistPanels and their histograms.
for (int i=0; i < NUM_HISTS; i++) {
fHistogram[i] = new Histogram ("Sensor "+i,
"Data", 25,0.0,10.0);
fHistPanel[i] = new StreamedHistPanel (fHistogram[i]);
// Add the histogram panels to the container panel
fHistsPanel.add (fHistPanel[i]);
// Get the output streams for each panel.
fDataOut[i] = fHistPanel[i].getOutputStream ();
}
makeHist ();
fGoButton.setText ("Stop");
fClearButton.setEnabled (false);
if (fInBrowser) fExitButton.setEnabled (false);
panel.add (fHistsPanel,"Center");
panel.add (control_panel,"South");
// Add text area with scrolling to the contentPane.
content_pane.add (panel);
} // init
public void actionPerformed (ActionEvent e) {
Object source = e.getSource ();
if (source == fGoButton || source == fTextField) {
String str_num_data_points = fTextField.getText ();
try {
fNumDataPoints = Integer.parseInt (str_num_data_points);
} catch (NumberFormatException ex) {
// Could open an error dialog here but just
// display a message on the browser status line.
showStatus ("Bad input value");
return;
}
if (!fMakingHist) {
makeHist ();
fGoButton.setText ("Stop");
fClearButton.setEnabled (false);
} else { // Stop button has been pushed
fGoButton.setText ("Go");
fClearButton.setEnabled (true);
fMakingHist = false;
}
} else if (source == fClearButton ) {
for (int i=0; i < NUM_HISTS; i++)
{ fHistogram[i].clear ();}
repaint ();
}else if (!fInBrowser)
System.exit (0);
} // actionPerformed
/** Create the histograms and start the timers. **/
void makeHist () {
// Only allow for one data maker at a time.
if (fMakingHist) return;
fMakingHist = true;
// Create the runnable object to fill the histograms
// The data will simualte sensors that return data with
// slightly different slopes and pedestals.
// The maximum delay between data readings will be 500msecs.
fMakeData =
new MakeSensorData (this, fDataOut, fNumDataPoints,
fSlope, fPedestal, 500);
Thread data_thread = new Thread (fMakeData);
// Before starting the filling, 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 ();
// Start the timer after 100ms and then repeat calls
// to run in PaintHistTask object every 250ms.
fTimer.schedule (new PaintHistTask (), 100, 250);
// Now start the data filling.
data_thread.start ();
return;
} // makeHist
/**
* Use the inner class technique to define the
* TimerTask subclass for signalling that the display
* should be updated.
**/
class PaintHistTask extends java.util.TimerTask {
public void run () {
fUpdateDisplay = true;
}
} // class PaintHistTask
/**
* Repaint the histogram display and turn off the
* update display flag. Return the makingHist flag
* to indicate if updating should continue.
**/
public boolean update (Object obj) {
// Don't update the display until the timer
// turns on the updateDisplay flag.
if ( fUpdateDisplay) {
// Possible this method called before outputPanel
// created in the init (). So check if it exists
// before attempting to repaint.
if (fHistsPanel != null) fHistsPanel.repaint ();
fUpdateDisplay = false;
}
return fMakingHist;
} // update
/** Called when the histogram filling is finished. **/
public void done () {
fMakingHist = false;
// Stop the histogram display updates.
fTimer.cancel ();
// Update one last time
fHistsPanel.repaint ();
// Reset the buttons.
fGoButton.setText ("Go");
fClearButton.setEnabled (true);
} // done
public static void main (String[] args) {
int frame_width=450;
int frame_height=300;
// Create applet and add to frame.
HistStreamApplet applet = new HistStreamApplet ();
applet.fInBrowser = false;
applet.init ();
// Following anonymous class used to close window & exit program
JFrame f = new JFrame ("Demo");
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
} // class HistStreamApplet