Richard G Baldwin (512) 223-4758, baldwin@austin.cc.tx.us, http://www2.austin.cc.tx.us/baldwin/

JDK 1.1, Introduction to the Toolkit Class, Peers, and Lightweight Components

Java Programming, Lecture Notes # 103, Revised 01/27/99.


Preface

Students in Prof. Baldwin's Intermediate Java Programming classes at ACC are responsible for knowing and understanding all of the material in this lesson.

The material in this lesson is very important. However, there is simply too much material to be covered in detail during lecture periods. Therefore, students in Prof. Baldwin's Intermediate Java Programming classes at ACC will be responsible for studying this material on their own, and bringing any questions regarding the material to class for discussion.

This lesson was originally written on December 1, 1997 using the software and documentation in the JDK 1.1.3 download package.

Sample program confirmed operational with JDK 1.2 on 1/27/99.

Introduction

The primary purpose of this lesson is to introduce you to the concept of the Toolkit class so that you will recognize it when you see it used in subsequent lessons. We will also provide a brief introduction to peers, and make mention of lightweight components.

The Toolkit class provides an interface to platform-specific services such as printing, fonts, images, and display parameters.

The Toolkit constructor is abstract and therefore, we never directly instantiate an object of type Toolkit. Rather, we obtain a Toolkit object by invoking the getDefaultToolkit() method. This gives us an object that is appropriate for our system.

For example, to emit an audible signal in a program, we would execute the following statement:  

Toolkit.getDefaultToolkit().beep();

Note however, that depending on your system setup, this may, or may not result in an audible signal (some systems provide the ability to silence audible signals).

There are many methods in the Toolkit class, and some of those methods are not of direct use. However, there are a fairly large number of methods of the Toolkit class that are quite useful, and often necessary. We will use many of these methods in subsequent lessons. A partial list of the useful methods with brief descriptions follows. You are referred to the JDK documentation for a complete list of all the methods with descriptions.  

  • beep() - Sounds an audible signal 
  • getImage() - Used to load an image file from a disk or URL. 
  • checkImage() - Used to check the construction status of an image 
  • createImage() - Three versions available to create an Image object from specified data 
  • prepareImage() - Prepares an image for rendering. 
  • getFontList() - Returns the names of the available fonts for this system. 
  • getFontMetrics() - Used to obtain information such as the height and width of a font. 
  • getPrintJob() - Gets a PrintJob object to use for printing 
  • getScreenResolution() - Returns the screen resolution in dots-per-inch. 
  • getScreenSize() - Gets the size of the screen. 
  • getSystemClipboard() - Gets an instance of the system clipboard that can be used to transfer data to other applications. 
  • getSystemEventQueue() - Allow you to post events to the system event queue. 

To elaborate, according to Java AWT Reference by John Zukowski:  

The Toolkit ... is an abstract class that provides an interface to platform-specific details like window size, available fonts, and printing. ... Although the Toolkit is used frequently, both directly and behind the scenes, you would never create any of these objects directly. When you need a Toolkit, you ask for it with the static method getDefaultToolkit() or the Component.getToolkit() method.

What are some of the situations where you might need to use a Toolkit? A partial list follows:  

  • To fetch an image in an application you might invoke getImage()
  • To obtain information about available fonts, you might use getFontList()
  • To obtain certain information about the color model, you might use getColorModel()
  • To obtain information about the screen, you might use getScreenSize() or getScreenResolution()
  • To work with the system clipboard, you might use getSystemClipboard()
  • To print, you might use getPrintJob()
  • To force an image to be loaded, you might use prepareImage()
  • To post events to the system event queue, you might use getSystemEventQueue() and the list goes on. 

Although the Toolkit class has a simple constructor, the class is abstract and therefore cannot be instantiated. As mentioned above, to get a usable Toolkit object, you must invoke the static getDefaultToolkit() method of the Toolkit class, or the getToolkit() method of the Component class.

As you work through the remaining lessons, be on the lookout for the use of these methods. A sample program is provided in the following section that illustrates how to use the Toolkit class.

Sample Program

This program illustrates the use of the Toolkit class to obtain system-specific information at runtime.

The program determines the width and height of the screen in pixels at runtime by invoking the getScreenSize() method on an object of the Toolkit class.

This method returns an object of type Dimension which contains two public data members named width and height. The values of these two public data members in the returned object define the width and height of the screen in pixels for the current system settings.

This information is used to set the size of a Frame object so that its width is half the screen width and its height is half the screen height.

The width and height values are also displayed in Label objects that are added to the Frame.

The program also uses a method named beep() of the Toolkit class to emit an audible signal when the image becomes visible (but may not work on all systems, depending on system setup).

If you change your system parameters to select a different resolution, and hence a different screen size (as measured in pixels) and rerun the program, the Frame object will still be half as wide as the screen and half as tall as the screen, illustrating the fact that the Toolkit class provides system-specific information (based on the most current system setup) to programs that use its methods.

Note the use of the getDefaultToolkit() method to obtain a system-specific object of type Toolkit.

Also note the use of an anonymous inner-class to terminate the program.

This program was tested using JDK 1.1.3 and JDK 1.2 under Win95.  

/*File Toolkit01.java
Copyright 1997, R.G.Baldwin

This program illustrates the use of the Toolkit class to 
obtain system-specific information at runtime.

This program was tested using JDK 1.1.3 under Win95.

**********************************************************/
import java.awt.*;
import java.awt.event.*;

class Toolkit01 extends Frame{ //controlling class

  public static void main(String[] args){
    new Toolkit01();//instantiate this object
   }//end main
  //=====================================================//
  
  public Toolkit01(){//constructor
    int width = //get width and height of screen in pixels
         Toolkit.getDefaultToolkit().getScreenSize().width;
    int height = 
        Toolkit.getDefaultToolkit().getScreenSize().height;

    //Set size of frame and decorate it
    this.setSize(width/2,height/2);
    this.setTitle("Copyright 1997, Baldwin");
    this.setBackground(Color.yellow);
    this.setLayout(new FlowLayout());

    //Display width and height of screen in Label objects
    this.add(new Label("" + width));
    this.add(new Label("" + height));
    
    this.setVisible(true);//make the Frame visible
    //Try to emit an audible signal
    Toolkit.getDefaultToolkit().beep();  
   
    //Anonymous inner-class listener to terminate program
    this.addWindowListener(
      new WindowAdapter(){//anonymous class definition
        public void windowClosing(WindowEvent e){
          System.exit(0);//terminate the program
        }//end windowClosing()
      }//end WindowAdapter
    );//end addWindowListener
  }//end constructor 
}//end class Toolkit01   
//=======================================================//

Peers

As of JDK 1.1.3, every component provided by the AWT (not Swing) is supported by a peer. The peer is the native implementation of that component.

For example, if you instantiate a Button object in your application, it corresponds to the native button implemented by the operating system.

For the most part, you as a Java programmer need be concerned only with your implementation of the Java class named Button. The relationship between your Button object and the native peer button is handled behind the scenes by the Java Virtual Machine.

There is at least one situation, however, where you do need to be concerned. This situation has to do with the order in which you do things. For example, if you compile and execute the following code:  

    Label newLabel = new Label("New Label"); 
    System.out.println(newLabel.getPreferredSize().width);
 
    this.add(newLabel);    
    System.out.println(newLabel.getPreferredSize().width);

you will find that you do not get valid data for the first invocation of the getPreferredSize() method but you do get valid data for the second invocation of the getPreferredSize() method, after the Label object has been added to its container which was already on the screen.

According to the book entitled Java AWT Reference by John Zukowski:  

Creating a Java component ... does not create the peer. An object's peer is created when the object's addNotify() method is called. This is usually when the component's container is added to the screen.

This explains the behavior of the code fragment listed above. Valid information about the preferred size of the Label object is not available until the peer is actually created (because the preferred size depends on system-dependent factors such as the size and style of the font in this case). However, the peer is not created until the Label object is added to its container by the invocation of the add() method. After the Label is added to its container, the inquiry returns valid information.

You need to be careful to avoid making inquiries about components before they have a peer. In this particular case, there was no compile-time error or runtime error. The value returned from the first invocation of getPreferredSize() was simply zero. Using this value later could lead to problems that might be difficult to find and fix.

I will finish this section with one final quotation from John Zukowski:  

The most important advice I can give you about the peer interfaces is not to worry about them. Unless you are porting Java to another platform, creating your own Toolkit, or adding any native component, you can ignore the peer interfaces.

Zukowski then goes on to provide several pages of good hard-core technical information about peer interfaces. If you have further interest in the topic, see his book.

Lightweight Components

Finally, be aware that JavaSoft is moving away from the exclusive use of peer components in an area known as "lightweight components." Lightweight components are components implemented completely in Java without a requirement to depend on the components provided by the operating system. You will learn how to create your own lightweight components in a subsequent lesson after we have covered the appropriate background material.

It can probably be expected that lightweight components will have both advantages and disadvantages , but they have a couple of significant characteristics:

Possibly in some cases, they may also be less responsive than heavyweight components, but I haven't seen that demonstrated as of December 1997.

The capability to implement lightweight components was introduced in JDK 1.1 with the advent of the lightweight framework.

In the future, the programmer will have a choice to use either lightweight or heavyweight components, or a mixture of the two. As of JDK 1.1.3, you already have that choice if you want to expend the effort to develop your own lightweight components. However, because of the necessity to develop appropriate artwork, and other factors as well (generally outside the realm of programming), the development of a lightweight component is not a trivial task, and the development of an entire library of lightweight components could be a significant task.

As of 12/1/97, Javasoft has published a large set of lightweight components in the pre-beta evaluation stage under the name Swing. This set includes components that are not available in JDK 1.1.3, such as progress indicators, sliders, tabbed notebooks, help bubbles, etc. They are currently available for downloading and evaluation at <http://java.sun.com/products/jfc/swingdoc-current/doc/index.html> but that URL is likely to change over time.

You may find it instructive to access the site and take a look at the Swing demos that you will find there.

-end-