The Web browser is no help either in providing an estimate of the length of download time required. Browsers know how much progress has been made on a particular file but not how many files need to be downloaded before your applet can run.
A solution is to give the users of your applet a progress indicator that shows how much of the applet has been loaded and how much is left to go. This article shows how to implement and use such an indicator.
ProgressBar and ClassPreLoader. In addition, the class that extends Applet must be redesigned to avoid latency problems.Class ProgressBar
The ProgressBar class implements a functionally minimal progress indicator. It is created with a title and a count of total items. It then
updates itself each time its updateProgress method is called. The progress bar disposes of itself when updateProgress has been called once for each item.
This class could be made to have much more functionality. However, doing so would increase the launch time for the applet (as the class would
be larger) and would also increase the latency. The code for class ProgressBar looks like this:
import java.awt.*;
public class ProgressBar extends Frame { private int Count; private int Max; private static final int FrameBottom = 24;
public ProgressBar (String Title, int TotalItems) { super(Title);
Count = 0; Max = TotalItems;
// Allowing this to be resized causes more trouble than it is worth // and the goal is for this to load and launch quickly! setResizable(false);
setLayout(null); addNotify(); resize (insets().left + insets().right + 379, insets().top + insets().bottom + FrameBottom); }
public synchronized void show() { move(50, 50); super.show(); }
// Update the count and then update the progress indicator. If we have // updated the progress indicator once for each item, dispose of the // progress indicator. public void updateProgress () { ++Count;
if (Count == Max) dispose(); else repaint(); }
// Paint the progress indicator. public void paint (Graphics g) { Dimension FrameDimension = size(); double PercentComplete = (double)Count * 100.0 /(double)Max; int BarPixelWidth = (FrameDimension.width * Count)/ Max;
// Fill the bar the appropriate percent full. g.setColor (Color.red); g.fillRect (0, 0, BarPixelWidth, FrameDimension.height);
// Build a string showing the % completed as a numeric value. String s = String.valueOf((int)PercentComplete) + " %";
// Set the color of the text. If we don't, it appears in the same color // as the rectangle making the text effectively invisible. g.setColor (Color.black);
// Calculate the width of the string in pixels. We use this to center // the string in the progress bar window. FontMetrics fm = g.getFontMetrics(g.getFont()); int StringPixelWidth = fm.stringWidth(s);
g.drawString(s, (FrameDimension.width - StringPixelWidth)/2, FrameBottom); }
public boolean handleEvent(Event event) { if (event.id == Event.WINDOW_DESTROY) { dispose(); return true; }
return super.handleEvent(event); } }
Class ClassPreLoader
The ClassPreLoader class loads Java classes while updating a status bar. ClassPreLoader has no methods other than the constructor. There is only one constructor, which takes two arguments -- a ProgressBar to update and an array of strings. Each string in the array is the name of a class that needs to be loaded before the applet
can run. The code for class ClassPreLoader looks like this:
class ClassPreLoader
{
public ClassPreLoader(ProgressBar theProgressBar, String classArray[])
{
int i;
for (i = 0; i < classArray.length; ++ i)
{
try
{
Class c = Class.forName(classArray[i]);
theProgressBar.updateProgress();
}
catch (Exception e)
{
// Do nothing.
}
}
}
}
Class MyApplet
The class that extends Applet needs to be redesigned slightly. Netscape Navigator 3.0 "helpfully" preloads class files it thinks it will need. Preloading
these classes takes precedence over running code that has already been downloaded. If the applet class needs other classes,
those classes are downloaded before the applet starts to run. This can add significantly to the time it takes for the progress
bar to display once an applet has started downloading.
To get around this time problem, the class that extends Applet must reference a minimum number of non-built-in Java classes. The example class below, MyApplet, runs as follows:
MyApplet class downloads itself.
ProgressBar class.
ClassPreLoader class.
MyAppletRunner class.
init method in class MyApplet that creates a progress bar, displays it, and then creates a new object of type ClassPreLoader which then loads the specified classes. Finally, the class MyAppletRunner gets created and actually runs the applet.
MyAppletRunner is in line with the init method of MyApplet, then any classes needed by MyAppletRunner will also be loaded before the progress bar is displayed. The trick here is to minimize the number of classes the browser
loads before displaying the progress bar. The code for class MyApplet looks something like this: import java.awt.*;
import java.applet.*;
public class MyApplet extends Applet
{
public void init()
{
// The classes needed by your applet. They have the same
// name as the *.class files (but without the .class).
// Don't bother including ClassPreLoader or ProgressBar.
String classArray[]
{
"FirstClassName",
"SecondClassName",
"ThirdClassName",
// Possible lots more class names in here.
"LastClassName"
};
super.init();
setLayout(null);
resize(6,6);
// Make and display the progress bar. The '+2'
// is because there are two time consuming steps
// in the constructor of MyAppletRunner, and we
// update the progress bar inside there, too.
ProgressBar theProgressBar =
new ProgressBar("My nifty applet downloading...", classArray.length + 2);
theProgressBar.show();
// Preload all the necessary classes, updating the progress bar as
// they are loaded.
ClassPreLoader myPreLoader = new ClassPreLoader(theProgressBar, classArray);
// The constructor for class MyAppletRunner implements the code that
// is traditionally in the init() method.
MyAppletRunner myApplet = new MyAppletRunner(theProgressBar);
}
public boolean handleEvent(Event event)
{
return super.handleEvent(event);
}
}
You can further reduce download time by moving the functionality of the ClassPreLoader into a method of the MyApplet class. This eliminates one class download with all the associated connection overhead.
Progress bar tutorialBy Anonymous on February 15, 2009, 11:46 pmreally useful
Reply | Read entire comment
View all comments