Using Images and Timers

The Waba foundation classes contain methods and classes to deal with images and timers. We'll explain the basics here along with some sample code that should give you a feel for how they can be used.

Loading Images

Let's start with images. The Image class in the waba.fx package represents an image.

In this example, we load an image called "hello.bmp" and draw it at location 10, 10 in the application window:

    public class MyApp extends MainWindow

    {

    Image img;

    public void onStart()

      {

      img = new Image("hello.bmp");

      }

    public void onPaint(Graphics g)

      {

      g.drawImage(img, 10, 10);

      }

So, how did we create the hello.bmp image? The hello.bmp image is a Microsoft BMP format image. BMP is a standard image format for bitmap images.

Waba supports 2, 16 and 256 color uncompressed BMP images. These image types are supported by most paint programs.

If you could use the Paint program that comes with Windows 95 or NT, you can save an image out as a "Monochrome Bitmap" BMP image to use it in a Waba program. In Paint Shop Pro (from JASC, Inc), you could save out an image as "BMP - OS/2 or Windows Bitmap" and "Windows RGB Encoded".

If you load BMP images in your program, you should include them in your program's WARP file.

Here is an example of executing a command to "warp up" all the classes and images in the current directory into a single WARP file:

    > warp c /q Hello *.class *.bmp

Using Images in Java Applets

If you distribute your Waba program as a Java applet, there is something you should know if your Waba program uses images: the image files should not be included in a JAR file.

Before we explain this in detail, let's review how to put a Waba program on the web so it can run as a Java applet in a web page.

You can put a Waba program up on the web as a Java applet by placing all your program's classes and all the Waba foundation classes in the WabaSDK up on the web under a directory such that the directory hierarchy looks like this:

    /index.html

    /hello.bmp

    /MyApp.class

    /waba/applet/Applet.class

    /waba/applet/Frame.class

    ..

    /waba/ui/PenEvent.class

    /waba/ui/Welcome.class

The following HTML code would make the applet appear in the index.html page:

    <applet code=waba/applet/Applet.class

     width=160 height=160>

    <param name=appClass value="MyApp">

    </applet>

To make the applet load faster, it's common to create a JAR file containing the applet's classes. A "jar" program is used to create and manage JAR files. The jar program is part of Java Development Kit distributions like the JDK from Sun Microsystems.

You can make a JAR file containing the Waba program as you normally would, but the trick is the JAR file should not contain the images used by your program.

It should only contain the program's classes:

    > jar cvf MyApp.jar *.class waba/applet/*.class

      waba/fx/*.class waba/io/*.class waba/sys/*.class

      waba/ui/*.class

The image files should be placed on the web site separate from the JAR file as follows:

    /index.html

    /hello.bmp

    /MyApp.jar

Then the HTML code that references the applet can be changed to load the applet from a JAR file:

    <applet code=waba/applet/Applet.class

     width=160 height=160 archive=MyApp.jar>

    <param name=appClass value="MyApp">

    </applet>

The image files can't be in the JAR file because some web browsers don't expect anything but .class files to exist in a JAR file.

Creating Images

There are times where you don't want to load an image and, instead, just want to create an image and draw in it yourself. One common use of off-screen images is as a drawing buffer to perform double-buffered drawing.

In this example, we create a 10x10 image with a black background and draw a white X in the image:

    Image img = new Image(10, 10);

    Graphics g = new Graphics(image);

    g.setColor(0, 0, 0);

    g.fillRect(0, 0, 10, 10);

    g.setColor(255, 255, 255);

    g.drawLine(0, 0, 9, 9);

    g.drawLine(0, 9, 9, 0);

Notice that we filled the image with a black background before drawing lines inside of it. The contents of an image are initially undefined.

When you want to draw an image to the screen, you don't have to draw the whole image. You can draw portions of it using the Graphics.copyRect() method. There are also various copy "modes" available to copy it with logical OR, AND and XOR functions.

The extended drawing modes are not available when running with the Java bridge classes (those in the WabaSDK). They are only available when running under a native WabaVM.

Timers

Now let's take a look at timers. Timers are associated with user-interface controls. Any user-interface control in a Waba program can have its own timer.

Timers are created and destroyed using two methods in the Control class:

    Timer Control.addTimer(int millis);

    boolean Control.removeTimer(Timer timer);

When a timer ticks, it posts a ControlEvent.TIMER event to the control associated with the timer.

Here we create a new control by subclassing the Control class. The control contains methods to start and stop blinking. The blinking timer fires 5 times a second (every 200 milliseconds).

    public class MyControl extends Control

    {

    Timer timer;

    public void startBlinking()

      {

      timer = addTimer(200);

      }

    public void stopBlinking()

      {

      removeTimer(timer);

      }

    public void onEvent(Event event)

      {

      if (event.type == ControlEvent.TIMER)

         blinkTheControl();

      }

The timer does not interrupt your program in the middle of an operation. It is scheduled along with other events. So, if your program is in the middle of computing something when the timer is supposed to tick, it will tick as soon as it can.

Time Stamps

Another method that is timing related but not directly related to timers is the method:

    int Vm.getTimeStamp();

This method returns a time stamp in milliseconds. It is a running timestamp which means when the value goes beyond the value 1073741824 (which is 1 << 30), it wraps around to 0. It has no connection to the current time, it is only useful when calculating relative times.

The current time is available by using the Time class.