How to deal with applet resizing in Netscape Navigator
This weekโs tip comes from Noah Green. Noah discusses his solution to the weird behavior of applets when they are resized.
When you resize the browser window in Netscape, it will always do the following to any applet running on the page:
1. Call its stop() method
2. Call both of its resize() methods (resize(int,int) and
resize (dimension) )
3. Call its start() method
If your program uses threads, you should be careful how you write your start and stop methods. In most sample applet code, the stop() method calls stop on any separate threads within the applet, and then sets them to null. This is because most people think of the stop() method as something called when the user leaves the page and wants to forget about it. But since Netscape calls stop() when you resize the window, your users would lose the appletโs state when they thought they were only making a minor adjustment.
The solution is to always suspend threads, not stop them, in the stop method. In the start() method, you resume them. For example:
public void stop() {
if (extraThread != null && extraThread.isAlive() )
extraThread.suspend()
..........
}
public void start() {
if (extraThread == null)
extraThread = new Thread();
else
extraThread.resume();
......
}
We still have a problem: how to dispose of threads once the user really is done. We donโt want all these suspended threads hanging around now, do we?
First, we need to distinguish when stop() is being called by leaving the page, and when itโs being called by resizing. The problem is that there is no way to do this. Recall that when Netscape does resizing, it calls stop() before it calls any resize() methods, not after, so the state is the same.
There are probably better solutions to this problem than my hack. But here it is anyway: create a new thread called killThread, a subclass of Thread whose run() body kills off all extra threads by calling the appletโs destroy() method. The thread will wait 5 seconds (more or less) before it does this. Hereโs such a thread:
class KillThread extends Thread {
Applet parent;
final int KILLTHREADINTERVAL = 5000; // 5 seconds
public KillThread (Applet p) {
super("killThread");
parent = p;
}
public void run () {
try {
sleep(KILLTHREADINTERVAL);
} catch (InterruptedException e) {}
parent.destroy();
}
}
Meanwhile, make sure your appletโs destroy() method is written to kill off extraThread, and this killThread:
public void destroy() {
if (extraThread != null) {
extraThread.stop();
extraThread = null;
}
if (killThread != null) {
killThread.stop();
killThread = null;
}
}
How do we use this killThread? We instantiate and run it at the beginning of the appletโs stop() method. We stop and kill it at the beginning of the appletโs start() method. In this way, we solve the problem of figuring out whether we were resizing or not. The sequence of events is:
1. Netscape calls the stop() method, and a killThread starts.
2. If 5 seconds elapse without the start() method being called, then the user has probably left the page. killThread calls destroy(), which terminates all the appletโs extant threads.
If start() is called again, then it means that this was only a resize. Stop and nullify the killThread before it wrecks everything. Resume all the suspended threads, and continue running.
Here are the final versions of the appletโs start() and stop() methods:
public void start() {
// If we were in the middle of kill thread
(caused by resizing)
// stop the killthread and start (i.e. resume)
extraThread.
// Otherwise just start as normal
if (killThread != null) {
killThread.stop();
System.out.println ("KILLTHREAD STOPPED");
killThread = null;
}
// Now start running the extraThread thread
if ( extraThread == null ) {
extraThread = new Thread(this);
extraThread.start();
}
else
extraThread.resume();
}
public void stop () {
// First suspend the extraThread thread
if ( (extraThread != null) &&
(extraThread.isAlive()) ) {
extraThread.suspend();
}
// Fire up a killthread, which will kill the
extraThread thread
// in 5 seconds unless start is called
if (killThread != null)
System.out.println ("ERROR - killThread
shouldn't exist");
else {
killThread = new KillThread(this);
killThread.start();
}
}
(NOTE: This assumes that we keep track of killThread and extraThread as object variables somewhere, which we would most likely be doing anyway.)
There you have it! With this stuff installed, you will never mess up an applet by resizing a Netscape browser again.
You might want to experiment with other browsers, although if they donโt do things the way Netscape does, chances are this code will not affect things adversely. Also, the 5-second time limit may need to be shortened or lengthened, depending on the speed of different systems. So far, 5 seconds seem to do it okay on all the systems weโve worked with.
Iโve seen a lot of applets out there that will โbreakโ if you resize your browser window; this fix should put an end to that problem. If anyone knows of a more elegant solution besides launching a killThread, Iโd love to hear about it! Happy coding.


