Scrollers

Introduction

One of the major dynamic contents on the World Wide Web is what we are going to cover in this article - scrollers. As you know, there are a variety of them, e.g. text-based, image-based, hybrid, vertical, horizontal, random, etc. Scrollers are mainly used to display dynamic messages that are updated all the time. Therefore, scrollers themselves must provide a simple way for people to feed messages into the programs without making any further programming effort. In addition, some general customizable parameters should be added to spice up the features, e.g. font size, font color, font style, scroll speed, etc.

I am going to walk through the codes of the two text-based scrollers and give an example of an image-based scroller. With just a little of modification, you should be able to customize them to suit your flavor. There are quite a few of similar Java applets at lots of websites. You may get get some inspirations from them. Check out Java Review Service (www.jars.com), Java Boutique (www.javaboutique.com), Java Repository (java.wiwi.uni-frankfurt.de), etc. All the demo files are downloadable: scroller.html, scroller.java, scrollerv.html, scrollerv.java, aipscroll.html, aipscroll.class, and aipbaby.gif.

Basics

Double buffering is used to prepare a duplicate off-screen graphics object, which mainly shows the change from the previous frame and is drawn only when it is completely ready. This is done in order to reduce screen flickering. Delay between two adjacent frames is used to control the screen refresh rate. step is used to control the scrolling speed. The smaller the step is, the smoother scrolling will appear on the screen. We also need a thread to keep track of painting activities to make sure everything is drawn in order.

A Text-Based Horizontal Scroller

The source code of the above scroller is listed in Fig 1 and its corresponding HTML is in Fig 2. Lines 1 - 5 import classes from JDK. Lines 10 - 11 are for the thread control. Line 12 is for the offscreen image and line 13 is for the offscreen graphics. Line 14 is for the text position on the screen. sw, sh, and sd are for text width, height, and descent respectively. Line 20 is for the message we want to to display. step in Line 23 is for scrolling speed. In init(), the first part from Line 30 - 40 is to read in all the parameters in the HTML file. Lines 42 - 43 set up the applet width and height and create the offscreen image and grphics. In start(), we start a new thread if no thread is running. In stop(), we stop a running thread. We control the scrolling step in lines 72 - 74 by x. Lines 62 - 65 override the default update() method. Lines 89 - 93 draw the background and frame on the offscreen graphics. Lines 95 - 102 get the font measures and set up the vertical position by centering the text. We draw a text shadow in lines 103 - 104. Lines 105 - 106 draw the real text. Line 107 refreshes the screen with the offscreen image. Line 110 - 123 use mouse as a toggle to start or stop the scrolling.

001 import java.awt.Graphics;
002 import java.awt.Font;
003 import java.awt.Color;
004 import java.awt.Image;
005 import java.applet.*;
006
007 public class scroller extends Applet implements Runnable
008    {
009    // general setup
010   Thread t = null;
011   boolean suspended = false;
012   Image oi;
013   Graphics og;
014   int x = 0, y = 0;
015   int width = 0, height = 0;
016   int sw, sh, sd;
017   boolean initialized = false;
018
019   // input params
020   String message = "Hello! Welcome to my page!";
021   String font = "Helvetica";
022   int fontSize = 12;
023   int step = 8, delay = 50;
024   int backR = 0, backG = 255, backB = 0;
025   int foreR = 255, foreG = 255, foreB = 255;
026
027   public void init()
028      {
029      // get all params
030      message = getParameter("message");
031      font = getParameter("font");
032      fontSize = Integer.parseInt(getParameter("fontsize"));
033      step = Integer.parseInt(getParameter("step"));
034      delay = Integer.parseInt(getParameter("delay"));
035      backR = Integer.parseInt(getParameter("backgroundr"));
036      backG = Integer.parseInt(getParameter("backgroundg"));
037      backB = Integer.parseInt(getParameter("backgroundb"));
038      foreR = Integer.parseInt(getParameter("foregroundr"));
039      foreG = Integer.parseInt(getParameter("foregroundg"));
040      foreB = Integer.parseInt(getParameter("foregroundb"));
041
042      // set up applet size and double buffering
043      width = size().width;
044      height = size().height;
045      resize(width, height);
046      oi = createImage(width, height);
047      og = oi.getGraphics();
048      }
049
050   public void start()
051      {
052      if (t == null)
053         {
054         t = new Thread(this);
055         t.start();
056         }
057      }
058
059   public void stop()
060      {
061      if (t != null && t.isAlive())
062         t.stop();
063      t = null;
064      }
065
066   public void run()
067      {
068      Thread.currentThread().setPriority(Thread.NORM_PRIORITY - 1);
069      while (true)
070         {
071         repaint();
072         x -= step;
073         if (x < -sw)
074            x = width;
075         try
076            {
077            Thread.sleep(delay);
078            }
079         catch (InterruptedException e) {}
080         }
081      }
082   public void update(Graphics g)
083      {
084      paint(g);
085      }
086
087   public void paint(Graphics g)
088      {
089      og.setFont(new Font(font, Font.BOLD, fontSize));
090      og.setColor(new Color(backR, backG, backB));
091      og.fillRect(0, 0, width - 1, height -1);
092      og.setColor(new Color(foreR, foreG, foreB));
093      og.drawRect(0, 0, width - 1, height -1);
094
095      if (initialized == false)
096         {
097         sw = (og.getFontMetrics()).stringWidth(message);
098         sh = (og.getFontMetrics()).getHeight();
099         sd = (og.getFontMetrics()).getDescent();
100         y = height - (height - sh) / 2 - sd;
101         initialized = true;
102         }
103      og.setColor(Color.black);
104      og.drawString(message, x + 1, y + 1);
105      og.setColor(new Color(foreR, foreG, foreB));
106      og.drawString(message, x, y);
107      g.drawImage(oi, 0, 0, this);
108      }
109
110   // use mouse to toggle animation
111   public boolean mouseDown(java.awt.Event evt, int x, int y)
112      {
113      if (suspended)
114         {
115         t.resume();
116         }
117      else
118         {
119         t.suspend();
120         }
121      suspended = !suspended;
122      return true;
123      }
124   } 

Fig 1: source code for the text-based horizontal scroller
<applet code=scroller.class width=400 height=50>
<param name=message value="This is a welcome message from the Complete Webmaster!">
<param name=font value=TimesRoman>
<param name=fontsize value=20>
<param name=step value=2>
<param name=delay value=50>
<param name=backgroundr value=215>
<param name=backgroundg value=215>
<param name=backgroundb value=0>
<param name=foregroundr value=0>
<param name=foregroundg value=0>
<param name=foregroundb value=255>
</applet> 

Fig 2: HTML example for the text-based horizontal scroller

A Text-Based Vertical Scroller

The source code of the vertical scroller is listed in Fig 3 and its corresponding HTML is in Fig 4. I explain the main differences from the previous program. nlines in line 19 is for the number of lines of messages. Line 20 is an array to contain all messages. Lines 30 - 33 read in all the input messages. Lines 75 - 79 update the vertical position and display the next message when the current message is moving out of sight. Line 105 horizontally centers all messages. Lines 102, 108, and 110 use the message with current id.

001 import java.awt.Graphics;
002 import java.awt.Font;
003 import java.awt.Color;
004 import java.awt.Image;
005 import java.applet.*;
006
007 public class scrollerv extends Applet implements Runnable
008    {
009    // general setup
010    Thread t = null;
011    boolean suspended = false;
012    Image oi;
013    Graphics og;
014    int x = 0, y = 0;
015    int width = 0, height = 0;
016    int sw, sh, sd;
017
018    // input params
019    int nlines, id = 0;
020    String [] message;
021    String font = "Helvetica";
022    int fontSize = 12;
023    int step = 8, delay = 50;
024    int backR = 0, backG = 255, backB = 0;
025    int foreR = 255, foreG = 255, foreB = 255;
026
027    public void init()
028       {
029       // get all params
030       nlines = Integer.parseInt(getParameter("nlines"));
031       message = new String[nlines];
032       for (int i = 0; i < nlines; i++)
033          message[i] = getParameter("message" + (i+1));
034       font = getParameter("font");
035       fontSize = Integer.parseInt(getParameter("fontsize"));
036       step = Integer.parseInt(getParameter("step"));
037       delay = Integer.parseInt(getParameter("delay"));
038       backR = Integer.parseInt(getParameter("backgroundr"));
039       backG = Integer.parseInt(getParameter("backgroundg"));
040       backB = Integer.parseInt(getParameter("backgroundb"));
041       foreR = Integer.parseInt(getParameter("foregroundr"));
042       foreG = Integer.parseInt(getParameter("foregroundg"));
043       foreB = Integer.parseInt(getParameter("foregroundb"));
044
045       // set up applet size and double buffering
046       width = size().width;
047       height = size().height;
048       resize(width, height);
049       oi = createImage(width, height);
050       og = oi.getGraphics();
051       }
052
053    public void start()
054       {
055       if (t == null)
056          {
057          t = new Thread(this);
058          t.start();
059          }
060       }
061
062    public void stop()
063       {
064       if (t != null && t.isAlive())
065         t.stop();
066       t = null;
067       }
068
069    public void run()
070       {
071       Thread.currentThread().setPriority(Thread.NORM_PRIORITY - 1);
072       while (true)
073          {
074          repaint();
075          y -= step;
076          if (y < -sh )
077             {
078             y = height;
079             id = (id + 1 + nlines) % nlines;
080             }
081          try
082             {
083             Thread.sleep(delay);
084             }
085          catch (InterruptedException e) {}
086          }
087       }
088
089    public void update(Graphics g)
090       {
091       paint(g);
092       }
093
094    public void paint(Graphics g)
095       {
096       og.setFont(new Font(font, Font.BOLD, fontSize));
097       og.setColor(new Color(backR, backG, backB));
098       og.fillRect(0, 0, width - 1, height -1);
099       og.setColor(new Color(foreR, foreG, foreB));
100       og.drawRect(0, 0, width - 1, height -1);
101 
102       sw = (og.getFontMetrics()).stringWidth(message[id]);
103       sh = (og.getFontMetrics()).getHeight();
104       sd = (og.getFontMetrics()).getDescent();
105       x = (width - sw) / 2;
106
107       og.setColor(Color.black);
108       og.drawString(message[id], x + 1, y + 1);
109       og.setColor(new Color(foreR, foreG, foreB));
110       og.drawString(message[id], x, y);
111       g.drawImage(oi, 0, 0, this);
112       }
113
114    // use mouse to toggle animation
115    public boolean mouseDown(java.awt.Event evt, int x, int y)
116       {
117       if (suspended)
118          {
119          t.resume();
120          }
121       else
122          {
123          t.suspend();
124          }
125       suspended = !suspended;
126       return true;
127       }
128    }

Fig 3: source code for the text-based vertical scroller
<applet code=scrollerv.class width=300 height=40>
<param name=nlines value=5>
<param name=message1 value="Hello, there!">
<param name=message2 value="Welcome to this page!">
<param name=message3 value="Enjoy your stay!">
<param name=message4 value="Come back soon!">
<param name=message5 value="Ciao! Sayonara!">
<param name=font value=TimesRoman>
<param name=fontsize value=20>
<param name=step value=2>
<param name=delay value=50>
<param name=backgroundr value=0>
<param name=backgroundg value=215>
<param name=backgroundb value=215>
<param name=foregroundr value=215>
<param name=foregroundg value=215>
<param name=foregroundb value=0>
</applet> 

Fig 4: HTML example for the text-based vertical scroller

An Example of Image-Based Scroller

aipscroll.gif

Figure 5: aipscroll (click on image)

We provide an example of image-based scroller. This example demonstrates the random scrolling behavior of an image. In fact, scrolling along a fixed direction is also possible. Please check out the comments in its HTML file. This is only another scroller example you might want to incorporate into your web page. aipscroll is a member of the AIP (Animation through Image Processing) package downloadable at http://www.cis.udel.edu/~cliu/sw.html.

Conclusion

We go through the details of the two text-based scrollers in this article and give an example of the image-based scroller. The first program is a single message display. With just a little bit of modification, we turn it into a multiplle-line vertical scroller. Both can be further improved by some other features, e.g. fading effect, mouse-activated linking capabilities. This article is just to show you one of the many possibilities in scrollers. More commonly used web features written in Java will come in this series of introduction.

NEXT: Clocks

Author: Chunyen Liu
Date: 12/21/98

More articles about Java
More articles by Chunyen Liu
Author Biography