MAIN
ABOUT
COURSES
ADVERTISE
SPONSORS
LINK TO US
CONTACT US

FREE ONLINE COURSES FOR THE INTERNET COMMUNITY
 

Introduction

Chapter 1: The basics in Java

Chapter 2: Your first applet

Chapter 3: Threads and animation

Chapter 4: Images and parameters

Chapter 5: Mouse messages

Links to applets and source code

FAQ

Basic Course in Special Effects and Game Programming in Java

by Aníbal Wainstein

The rights to the English version of this course are reserved and owned by Mandomartis Software Company and Scandinavia Online. The course may not be displayed on other web sites other than this one. If you should happen see this content somewhere else on the Internet then please contact us.

Chapter 4
Images and parameters

Last updated 1999-06-04


CONTENT

4.0 Images

Java applets and applications can read two types of image formats, JPEG and GIF format. Java also support transparent GIF89 images, these images can get other images behind them to "shine through" the transparency pixels. Note that in spite of this an applet can never be made transparent, which means that you cannot have a transparent GIF89 image in an applet and at the same time get the homepage background to shine through. It is the ability to load images and to process or animate them, that makes Java applets to an alternative against GIF89 animations. When you, on top of this, are able to add interaction to these animations then it gets to be a very superior alternative. In this chapter we will review how to handle and how to work with images.

4.0.1 How to load and handle images in Java applets (the Image class)

It is the Image class that handles images. If an applet is going to load images then it needs to know where the image is and what the file is named. As we have mentioned in the last section, the images must be in JPEG or GIF87/89 format. You can load an image with the getImage() method:

public Image logo;



public void init()

{

    logo=getImage(getDocumentBase(),"logo.jpg");

}

The getImage() method requires two arguments: one is an URL to the location where the image is and the other argument is the name of the file in the form of a string. The getDocumentBase() method will return an URL object which is the location of the applet's class file. The applet will be able to load the image "logo.jpg" if it is in the same catalog as the class file. Later on in chapter 6, we will look more at the URL class. With this code the image can now be loaded. Please note that the image is not immediately fully read by the applet, this can lead to funny effects as you will see later. An image can later on be drawn with the Graphics method drawImage() in the following way:

public void paint(Graphics g)

{

    g.drawImage(logo,0,0,this)

}

There are several drawImage() methods, but the simplest is the one used in the code example here above. This method we will use extensively in the course. The arguments are an Image object, the x and y positions for the image and a reference to the applet itself (this). Click here to see how it works. Please note that the image should have the same dimensions as the applet.

 

4.0.2 Improve the image loading with MediaTracker 

Did you notice that you could practically see the image being loaded in the last section's example? This was because the paint() method is called several times during the image download! The reason that Sun chose to make the system this way, is that they wanted to keep the effect of seeing something while waiting for a page to download. This was usual in older web browsers (new web browsers such as IE4.0, will only display the image when it is fully downloaded, unless it does not happen to be an interlaced GIF image). The paint() method will be called arbitrary by the web browser when it has managed to download a new piece of the image. This could cause problems and can look bad in some applets. But there is a solution, there is a class named MediaTracker, which makes sure that the image is fully downloaded before you use it.
Let us rewrite the init() method in the last section to:

public void init()

{



    logo=getImage(getDocumentBase(),"logo.jpg");



    //The following line creates a tracker.

    MediaTracker tracker=new MediaTracker(this);



    //We give the image we want to track the

    //identification number 0.

    tracker.addImage(logo,0);



    //With the waitForAll() method the image can

    //be loaded. It will throw an InterrupterException

    //if something happens.

    try

    {

        tracker.waitForAll();

    }

    catch(InterruptedException e)

    {

        System.out.println("Something happened while reading image...");

    }

}

A tracker object requires a reference to the applet when it is created (you get that with "this"). With the addImage() method we can give the image the ID number 0, in the methods internal "download list". Please note that you cannot give several images the same ID number, each must have a unique number. Finally, we can use the waitForAll() method that makes sure to load all the images. This method throws an exception that you must "catch".

Click here to see an improved version of the last section's applet. In this example the difference is minimal and maybe not even noticeable, but in more complicated graphics applets it is a necessity.

 

4.0.3 Arrays

Now we have come to the point where we cannot work without arrays no longer. An array is a group of variables that are all of the same type. You can compare arrays with a cabinet and it's drawers. Imagine that you have a drawer that represents a variable, the drawer is part of a cabinet together with other identical drawers. The cabinet that contains the drawer is then the array. A variable in an array is called element. When you initialize an array you must always specify how many variables it will contain. This is done with the new keyword. You can also specify the number of dimensions an array will have, but that we will not review here. Imagine now that we want to create an array with 5 integer numbers, then first we declare an array of integers:

int myarray[];

The two brackets [] are used to indicate that the variable "myarray" is an array. Now we must initialize the array and specify how many elements it will contain:

myarray = new int[5];

The array "myarray" now contains 5 integers, you can access them by writing:

int firstelement=myarray[0];

int secondelement=myarray[1];

int thirdelement=myarray[2];

int fourthelement=myarray[3];

int lastelement=myarray[4];

The number within the brackes is pointing on the first element in the array and it is called an index. Please note that arrays are always zero based, which means that the first element is accessed by specifying zero (and not 1 as one may think). In the example above we access the last integer by writing a 4. So 4 is the maximum for the index number even though the size of the array is 5. You can also initialize and declare the size for an array in a single line:

int myarray[] = new int[5];

You may now think that you know everything you need to know about arrays? Not yet... Please note that what we have declared so far have not had classes as elements. Now we will look at the process of creating arrays of classes. Assume that we want to create an array of 30 String objects:

String mystrings[] = new String[30];

It looks the same as the example above but "int" has been exchanged for "String" instead! Yes, of course! But this does not mean that we are finished yet. What you have managed to create are just an array with references. Now you must initialize each unique array element:

mystrings[0]=new String("String 0");

mystrings[1]=new String("String 1");

mystrings[2]=new String("String 2");

...

mystrings[29]=new String("String 29");

It looks worksome, right? Well, you get used to it! Sometimes you can find smart ways to make this element initializing automatic. The example above can be written like this instead:

String mystrings[]=new String[30];

for (int i=0; i<30; i++)

{

    mystrings[i]=new String("String "+i);

} 

Please note that if you try to add an integer, float or double to a String then the number will be automatically converted to a String object before being added. I have used this trick above in the initialization of the string ("String " + i). A great relief is that arrays with integers and floating point numbers always have the value zero, at the beginning, so these do not have to be initialized if you happen to depend on that.


4.0.4 An animation applet (AppletAnimator) 

With the applet AppletAnimator we will try to imitate the effect that the animated GIF89 images give. Let us load several images in the init() method:

//The Image array "images" must be global. 

Image images[];



//The variable "currentimage" will hold the

//image currently being displayed.

int currentimage=0;



public void init()

{

    //Init "images" to have four elements.

    images=new Image[4];

    MediaTracker tracker=new MediaTracker(this);





    //We use a for-loop to load the images.

    for (int i=0; i<4; i++)

    {

        //"image0.gif","image1.gif",...,"image3.gif" will be

        //loaded.

        images[i]=getImage(getDocumentBase(),"image"+i+".gif");



        //The ID for each image must be increased
//for each image that is added to the
//tracker.
tracker.addImage(images[i],i); } //Finally we must make sure the tracker load the images. try {tracker.waitForAll();} catch(InterruptedException e) { System.out.println("Something happened while reading images..."); } }  

We begin by initializing the image array with 4 Image objects. The getImage() method will read the images and the for loop with make sure that the images end up in the right place in the array and in the tracker. That is, "images[0]" will reference "image0.gif" at the same time that it is added to the location 0, in the tracker's list. The variable "images[1] will reference "image1.gif" and be added to the location 1, in the tracker's list, and so on.

 
"images"-index Filename MediaTracker list
0
"image0.gif"
0
1
"image1.gif"
1
2
"image2.gif"
2
3
"image3.gif"
3

The applet will be a thread based applet with start() and stop() methods which you can read more about in section 3.0.1. The Run() method looks almost the same as in the textscroller example in chapter 3:

public void run()

{

    while (true)

    {

        update(getGraphics());



        //"currentimage" is increased so that the next

        //image is displayed in the next screen update.

        currentimage++;



        //However, "currentimage" must not exceed the

        //index value of 3.

        if (currentimage>3) currentimage=0;

        try {Thread.sleep(200);}

        catch(InterruptedException e) {}

    }

} 

The only change we have made in the textscroller's run() method is the handling of the "currentimage" variable. This variable will be used as index so that the applet will change image every 200 millisecond (5 times per second). The paint() method will look like this:

public synchronized void paint(Graphics g)

{

    //The integer "currentimage" is used as

    //index for the "images" array.

    g.drawImage(images[currentimage],0,0,this);

}

The images we will animate look like this:

The result of the animation will be that the arrow will appear to being rotated. This is not very interesting to see and we will in a later chapter review how we can do this with only one image and using image processing. Click here to see the applet.

4.1 Applet parameters 

The Java language would never have had such a big breakthrough on the Internet if it had not been for the possibility to configure Java applets. Without configurable Java applets, the Java technology would have stayed at the hands of the developers and never got to the web designers. The applet parameters is what makes an applet recyclable and available for everybody. It is a glorious feeling to randomly surf into a homepage that is using the applet that you have developed and reconfigurated. With parameters you can change almost anything in an applet such as the images used, colors, texts, font styles and more. Parameters also simplify your work as a programmer due to the simplicity to change parameter values and not having to change variables directly in the source code.

4.1.1 Working with getParameter()

It is very simple to read a parameter. Look at the following HTML code:

<APPLET CODE="myapplet.class" WIDTH=200 HEIGHT=100>

<PARAM name="myparameter" value="Long live Java!">

</APPLET>

In HTML, PARAM is used to specify a parameter, where "name" stands for the name of the parameter and "value" for the content. The method getParameter() always return a String and can, for instance, fetch "myparameter" like this:

String oneparameter=getParameter("myparameter");

Now "oneparameter" will contain the phase "Long live Java!". You may have how many parameters as you like, theoretically. However note that each parameter must have an unique name label. To simplify your work and to make your source code easy to read you should always read parameters in the init() method. The alternative is to put these lines in the run() method which will make your code difficult to read.

4.1.2 How to read an integer as a parameter (getIntegerParameter())

As we saw in the last section, getParameter() always return a string. If you want to read an integer instead, then you can use the following method:

public int getIntegerParameter(String name, int base)

{

    String value=getParameter(name);

    int intvalue;

    try {intvalue=Integer.parseInt(value,base);}

    catch (NumberFormatException e) {return 0;}

    return intvalue;

}

The method above is always good to have in an configurable applet, so you should always have the habit of pasting these lines into your source code, if you are going to make such an applet. The Integer class in Java is used to handle integers, but please note carefully now: "Integer" is NOT the same as "int". Integer is a class with methods while int is just a data type. A useful method that Integer has, is the static method parseInt() that converts a String to an integer ("int"). The other argument in parseInt() is the number base that may be decimal or hexadecimal (number base 10 or 16 respectively). The decimal number base is the normal number base system you use on your everyday life. If you are a web designer then you should also know the hexadecimal number system when you specify colors (that is if you write the HTML code yourself without a graphical HTML editor). You will later see the use of this when we specify colors for the textscroll applet.

4.1.3 AppletAnimator II, now configurable

There are not many changes that must be done in the AppletAnimator applet from section 4.0.4 to make it configurable. We start by adding a variable, "maxitems", which will indicate the number of images the user has specified in the applet parameters. The value for this variable must be specified by the user as a parameter, the name will also be called "maxitems":

//"maxitems" will be used to indicate the number of

//images that exist.

int maxitems=0;



//"sleeptime" indicates the delay between each image

//in milliseconds. 

int sleeptime=0;

Image images[];

int currentimage=0;



public void init()

{

    ///Get the value of the parameter "maxitems"

    //with the number base 10. 

    maxitems=getIntegerParameter("maxitems",10);



    /Get the value of the parameter "sleeptime". 

    sleeptime=getIntegerParameter("sleeptime",10);



    //The array "images" will have "maxitems" number

    //of elements.

    images=new Image[maxitems];

    MediaTracker tracker=new MediaTracker(this);

    for (int i=0; i<maxitems; i++)

    {

        //The following line will read the values of the

        //parameters "image0", "image1", "image2" and so on

        //up to the value that maxitems indicates. It will also

        //use the strings to load the files specified in those

        //parameters.

        images[i]=getImage(getDocumentBase()

            ,getParameter("image"+i));



        //The ID number for each image must be increased

        //for each image you add to the tracker.

        tracker.addImage(images[i],i);

    }



    //Finally we make sure that the tracker loads the images.

    try {tracker.waitForAll();}

    catch(InterruptedException e)

    {

        System.out.println("Something happened while reading images...");

    }

}         

The applet will start first by reading the value of "maxitems". This variable must contain the exact number of image parameters that will be read by the applet. The variable "sleeptime" indicates the delay between each image frame, which may be very useful to implement. The file name for each image is specified in the parameters "image0", "image1" and so on. What happens is that the for loop reads a parameter and directly uses it's value to load the image file and adds it to the tracker's list. The configuration for getting the same effect as the example in section 4.0.4 would then look like this:

<APPLET CODE="appletanimator2.class" WIDTH=100 HEIGHT=100>

<PARAM name="maxitems" value="4">

<PARAM name="sleeptime" value="200">

<PARAM name="image0" value="image0.gif">

<PARAM name="image1" value="image1.gif">

<PARAM name="image2" value="image2.gif">

<PARAM name="image3" value="image3.gif">

</APPLET>

The applet is not yet ready. We need to make two small changes in the run() method:

public void run()

{

    while (true)

    {

        update(getGraphics());



        //"currentimage" is increased so that the next

        //image is displayed in the next screen update.

        currentimage++;



        //However it must not exceed the value

        //of maxitems minus 1.

        if (currentimage>maxitems-1) currentimage=0;



        //The variable sleeptime sets

        //the delay in milliseconds.  

        try {Thread.sleep(sleeptime);}

        catch(InterruptedException e) {}

    }

} 

Please note that "maxitems-1" is the upper limit for the "currentimage" variable and the delay is now set by the "sleeptime" variable. At last it is time to present our first configurable applet! To demonstrate how the same applet can be reconfigurated and look completely different, we use it as a simple slide show with six texture images. We do this by increasing the delay to 2000 milliseconds (2 seconds) and setting "maxitems" to 6. Click here!

4.1.4 A configurable and effectfull image slide show (SlideShow)

Even if AppletAnimator II can be used to display images, yet it is not very impressive. We will now develop an animated slide show that slowly translates an image from a random location until it covers the old image completely. At last we are about to use random numbers. There is a very useful class in Java which is called Math. This class contains mostly static methods, so you do not have to create a Math-object to use these, you can call them directly. A very important method is the random() method. It returns a double floating point random number between 0 and 0.9999999... By multiplying with 10, you could get random numbers between 0 and 9. Please note that when you type cast a double to an integer, then the number will be rounded to the lowest integer value. Look at the following line:

int randomnumber = (int)(Math.random()*2.0);

The variable "randomnumber" will be set to 0 or 1. In the slide show we will use random numbers to indicate from what corner an image is going to be translated from. Actually to make this applet, we can just take all the variables and methods in the AppletAnimatorII applet and use these with just one change in the run() and paint() methods. We must also add the following global variables below the declaration of the "currentimage" variable:

int nextimage = 0;

int nextimagexposition = 0;

int nextimageyposition = 0;

These variables indicates what image will be animated into the applet screen and what it's current position is. The paint() method will then look like this:

public synchronized void paint(Graphics g)

{

    g.drawImage(images[currentimage],0,0,this);



    //The following image is drawn on top of the last

    //image.

    g.drawImage(images[nextimage]

        ,nextimagexposition,nextimageyposition,this);

}

The run() method will be a bit more complicated. We must for the first time find out what the applet dimensions are, because the person that will use the applet will probably change the dimensions. You do that with the size() method, which returns a Dimension object. With this object, we can find out the applet dimensions with it's internal variables, "width" and "height".

public void run()

{

    //We must find out the applet's dimension and save it

    //in the "d" variable. We can now get the applet

    //width and height by writing d.width and d.height.

    Dimension d=size();



    //The "displacement" variables specify the

    //starting coordinates for the image.

    int displacementx=0;

    int displacementy=0;



    //"pathsize" will be used to know what distance

    //that the new image will be moved.

    int pathsize=0;



    //"currentimage" is initialized to the first image,

    //followed by the next image, who becomes image

    //number 2, and so on.

    currentimage=0;

    nextimage=1;

    while (true)

    {

        //We calculate from which direction that

        //the new image should be moved from.

        int directionx=(int) (Math.random()*3.0)-1;

        int directiony=(int) (Math.random()*3.0)-1;



        //"directionx" and "directiony" may have

        //three values: -1, 0 and 1. It is not

        //interesting if both variables get the value 0

        //at the same time so therefore we change

        //"directiony" so that the effect becomes

        //more interesting.

        if (directionx==0 && directiony==0) directiony=1;



        //The variable "pathsize" is set to the applet

        //width or height depending on what side is the

        //shortest.

        if (d.width<d.height) pathsize=d.width;

        else pathsize=d.height;



        //The following line is the protection to the

        //problem if the user should onlyu specify one

        //image.

        if (nextimage>maxitems-1) nextimage=0;



        //The following loop handles the screen update

        //during the animation. It will move the image

        //the number of times specifies by "pathsize",

        //which is the short side of the applet screen.

        for (int i=0; i<=pathsize; i++)

        {

            //The image positions are moved

            //with the fraction (i/pathsize).

            nextimagexposition=displacementx

                -directionx*(i*d.width)/pathsize;

            nextimageyposition=displacementy

                -directiony*(i*d.height)/pathsize;

            update(getGraphics());

            try {Thread.sleep(sleeptime);}

            catch(InterruptedException e) {}

        }

        //When the translation is finished,

        //then "currentimage" is set to the new

        //image.

        currentimage=nextimage;



        //We increase "nextimage" so that it points to the

        //next image. At the same time we make sure that

        //"nextimage" extends above the array index but

        //that it is forced to start over from 0 if it does.

        nextimage++;

        if (nextimage>maxitems-1) nextimage=0;

}

The applet begins by placing an image out of visual range of the spectator, that is outside the applet screen. Slowly the image is translated to the center, one pixel at the time. A problem that can appear here, is the case when the applet is a rectangle and not a quadrate. Because then the applet must move the image with different horizontal and vertical steps. Therefore we use the short side of the applet screen and use it in the for loop to count to the number of pixels (the variable "pathsize"). We calculate a percent of how much the image must move (i/pathsize) and multiplicate this with d.width or d.height to get the total horizontal and vertical distance that it has translated and the new x and y position for the image.

The problem here is, because we are working with integers, we must make the division last. Therefore we write ((i*d.width)/pathsize) instead. Or else (i/pathsize) will always give the result zero because the value of "pathsize" is larger than "i". This is important, if you divide a smaller integer with a larger integer, then the result is always zero.

Finally we must also multiply this expression with "directionx" or "directiony", so that the image moves in the right direction and deduce this expression from "displacementx" and "displacementy" respectively, which are the images start coordinates.

The image demonstrates how the slide show works. The new image "nextimage" will be translated over the old image "currentimage".

After the for loop, we set "currentimage" to indicate the new image and increase "nextimage" so that it points to the next image in the slide show. If "nextimage" is pointing at the last image, then we set it to zero, so that it points to the first image instead (zero index). The result is that the images will rotate around in the slide show, so that the effect never ends. This line must also be used before the for loop, in the case that the user for some strange reason would like to specify just one image in the applet. This must be done in order to keep the applet from crashing. Now you can look at the result by clicking here.

You are disappointed, right? All this trouble just for a flimmering applet! The problem with the applet is, that when the first image has been drawn in the paint() method with drawImage(), then the applet screen is updated immediately. It will therefore fully display the old image before it finds the time to cover it with the next image. We must therefore find a way to prevent the applet screen to be updated between the two drawImage() calls. It is here we will have use for the double buffering technique, which will be discussed in the next section of this chapter.

4.2 Double buffering 

Double buffering is a technique used in almost any programming languages by game and special effect developers. When you draw lines, rectangles, texts and images directly to the screen, then you can in principle see when every object is drawn. This is not good if you only want the spectator to see the end result and nothing more. As we have seen with the textscroller and slideshow examples, this can cause flimmering. To avoid this, you draw first on a buffer (that is why it is called "double buffering"). The buffer is an image that you draw on "in secret" and do not show it to the spectator until it is finished. In Java you do this by creating an image as large as the applet, and then you get a Graphics object connected to this image. When you have finished drawing then you call the paint() method that displays the buffer image on the screen.

4.2.1 SlideShow II, now without flimmering

To add double buffering to the slideshow applet in the last section, me must first declare a global Image variable and a Graphics variable that we initialize in the init() method. Add the following variables to the global applet variables (add them under the declaration of the "nextimagepositiony" variable):

//"bufferimage" is used as the buffer and

//"bufferg" is used to draw on this buffer.

Image bufferimage;

Graphics bufferg;



//"delay" will be used instead of "sleeptime" to

//delay the each animation. "sleeptime" will be used to

//add a configurable delay between each image instead.

int delay=0;

Now that we are in the process of changing the applet, we can take the opportunity to add a new parameter, "delay". This variable will be used instead of "sleeptime" as a delay in the animation. The variable "sleeptime" will be used as the pause between each next image instead. Now the user of this applet will be able to specify a delay before the next image is animated. To create the graphics buffer we write the following lines and add them last in the init() method:

//Fetch the size for the applet.

Dimension d=size();



//createImage() creates an empty image

//that has the same dimensions as the

//applet screen.

bufferimage=createImage(d.width,d.height);



//"bufferg" is now associated with the

//buffer image.

bufferg=bufferimage.getGraphics();

delay=getIntegerParameter("delay",10);

The only thing we have to do now is to see to that the two images are drawn in the buffer first and not directly on the screen. This is done in the paint() method:

public synchronized void paint(Graphics g)

{

    //First we should check that "bufferg"

    //is initialized, it is not always sure that it

    //is.

    if (bufferg!=null)

    {

        //We draw the two images into the buffer first.

        bufferg.drawImage(images[currentimage],0,0,this);

        bufferg.drawImage(images[nextimage]

             ,nextimagexposition,nextimageyposition,this);



        //Now we draw the buffer image into the applet

        //screen.

        g.drawImage(bufferimage,0,0,this);

    }

}

There are some changes that must be done in the run() method too, now that we have changed the parameters:

public void run()

{

    Dimension d=size();

    int displacementx=0;

    int displacementy=0;

    int pathsize=0;

    currentimage=0;

    nextimage=1;

    while (true)

    {

        int directionx=(int) (Math.random()*3.0)-1;

        int directiony=(int) (Math.random()*3.0)-1;

        if (directionx==0 && directiony==0) directiony=1;

        if (d.width<d.height) pathsize=d.width;

        else pathsize=d.height;

        displacementx=directionx*d.width;

        displacementy=directiony*d.height;

        if (nextimage>maxitems-1) nextimage=0;

        for (int i=0; i<=pathsize; i++)

        {

            nextimagexposition=displacementx

                -directionx*(i*d.width)/pathsize;

            nextimageyposition=displacementy

                -directiony*(i*d.height)/pathsize;

            update(getGraphics());



            //Now "delay" is the delay in the loop.

            try {Thread.sleep(delay);}

            catch(InterruptedException e) {}

        }

        //"sleeptime" is used outside the loop.

        try {Thread.sleep(sleeptime);}

        catch(InterruptedException e) {}

        currentimage=nextimage;

        nextimage++;

        if (nextimage>maxitems-1) nextimage=0;

    }

}

We add a new delay outside the for loop and use the "sleeptime" variable there instead. Now the applet user can specify a delay before the next image starts rolling in. Now the applet should be completely finished. Do not forget to add the HTML parameter "delay" and set this to 20 before testing the applet. Set the parameter "sleeptime" to 1000 milliseconds or more. Click here to look at the applet. Is it not beautiful?

4.2.2 A configurable TextScroller (TextScroller II)

As you may remember, the textscroller i chapter 3 was flimmering. We can fix it now that we know the double buffering technique. At the same time we make it more configurable. Let us start by adding and modifying some variables first:

public Thread animationthread = null;

public String message;

public int x=100;

Image bufferimage;

Graphics bufferg;



//The following colors are fetched as

//HEXADECIMAL parameters and are used

//to set the background and text color

//of the applet.

Color backgroundcolor,textcolor;



//The "delay" variable is used as a delay

//for each picture frame.

int delay=0;

We have added some variables to set the background and foreground colors. The "delay" variable will be the delay in the animation, as it was in the slideshow applet. Do not forget to paste the getIntegerParameter() method. The init() method must also be altered a bit:

public void init()

{

    //We read the message as a parameter instead at the same

    //time as we read a paramter called "delay" for the

    //picture delay.

    message=getParameter("message");

    delay=getIntegerParameter("delay",10);



    //Please note that we read the values in

    //HEXADECIMAL form (with the base 16)

    //and then create a color.

    backgroundcolor=

        new Color(getIntegerParameter("backgroundcolor",16));

    textcolor=new Color(getIntegerParameter("textcolor",16));



    //The following lines are just copied from

    //slideshow2.java

    Dimension d=size();

    bufferimage=createImage(d.width,d.height);

    bufferg=bufferimage.getGraphics();

}

Please note that we get the colors for the applet with the getIntegerParameter() method and specifying that we want to read them in the number base 16, instead of 10. This is done so that these parameters can be specified with hexadecimal numbers by the applet user. The parameters could then look like this:

<APPLET CODE="textscroller2.class" WIDTH=100 HEIGHT=20>

<PARAM name="message" 

value="This is textscroller II, now configurable">

<PARAM name="backgroundcolor" value="ff0000">

<PARAM name="textcolor" value="0000ff">

<PARAM name="delay" value="50">

</APPLET>

We have set the background color to red (FF0000) and the text color to blue (0000FF). If you are not used to hexadecimal color values then maybe the following table may be useful:

Red FF0000
Green 00FF00
Blue 0000FF
Cyan 00FFFF
Yellow FFFF00
Magenta FF00FF
Black 000000
Dark Gray 7F7F7F
Light Gray AFAFAF
White FFFFFF
Orange FF7F00
Dark red 7F0000
Dark green 007F00
Dark blue 00007F

All the drawing in the paint() method must be done in the buffer, instead of directly in the applet screen. When it is finished, then the buffer is displayed on the screen:

public synchronized void paint(Graphics g)

{

    //It is always a good idea to check

    //that bufferg has been initialized.

    if (bufferg!=null)

    {

        //Paint the screen with the fetched

        //background color.

        bufferg.setColor(backgroundcolor);

        bufferg.fillRect(0,0,100,20);



        //Draw the message starting from

        //position "x".

        bufferg.setColor(textcolor);

        bufferg.drawString(message,x,12);

        g.drawImage(bufferimage,0,0,this);

        if (x<-400) x=100;

        x--;

    }

}

Note that we use the variables "backgroundcolor" and "textcolor" to specify the background color and the text color for the applet. Finally we make a small change in the run() method so that the frame delay for the applet can be set:

public void run()

{

    while (true)

    {

        update(getGraphics());



        //The "delay" variable now makes

        //the delay configurable.

        try {Thread.sleep(delay);}

        catch(InterruptedException e) {}

    }

}

Now the applet is ready. You should know that the text's length is limited and the applet dimensions must be 100x20 pixels. It does not make sense to change the dimensions right now, when you cannot control the text size anyway. You will learn this in chapter 6. Click here to see the applet.

Now you may feel ready to start your own Java company and flood the Internet with your applets, after this chapter. You would even now manage rather well as a special effects programmer, but there are some pieces left in your education. Some of them we will review in the next chapter which is about mouse messages.


 

Copyright © 1999-2005 Mandomartis Software Company