YOUR FEEDBACK
Verizon Becomes a Counter-Android Linux Convert
JNels wrote: Hey - Jeffrey Nelson here at Verizon Wireless. Not a bit of ...
SOA World Conference
Virtualization Conference
$200 Savings Expire May 16, 2008... – Register Today!


2007 West
GOLD SPONSORS:
Active Endpoints
Your SOA Needs BPEL for Orchestration
BEA
Virtualized SOA: Adaptive Infrastructure for Demanding Applications
Nexaweb
Overcoming Bandwidth Challenges with Nexaweb
TIBCO
What is Service Virtualization?
SILVER SPONSORS:
WSO2
Using Web Services Technologies and FOSS Solutions
Click For 2007 East
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
SYS-CON.TV
POWERBUILDER LINKS YOU MUST CLICK ON


Using Graphics in Your Applet

Digg This!

In Part 1 (PBDJ, Vol. 8, issue 5) I showed you how to use simple graphics within your applet. Polygons, ovals, lines, and text cover a lot of ground.

The remaining graphic object you need is an image. Images in Java are bitmapped GIF or JPEG files that can contain pictures of just about anything. You can use any program to create them as long as that program can save in the GIF or JPEG format. In Part 2, I show how to add niceties, such as color and fonts, to your applet.

Images displayed by Java applets are retrieved from the Web via a URL that points to the image file. An applet that displays a picture must have a URL applied to the image it's going to display. Images can be stored on a Web server, a local hard drive, or anywhere else the applet can point to via a URL.

Make sure you put your images somewhere the person viewing the applet can access them. A file URL that points to your local hard drive may work while you're developing an applet, but it won't be of much use to someone who comes in over the Web.

Typically you'll put images in the same directory as either the applet or the HTML file. Though it doesn't absolutely have to be in one of these two locations, storing it there will probably be more convenient. Put the image with the applet .class file if the image will be used for all instances of the applet. Put the applet with the HTML file if different instances of the applet will use different images.

A third alternative is to put all the images in a common location and use PARAMs in the HTML file to tell Java where the images are. If you know the exact URL for the image you wish to load, you can load it with the getImage() method:

URL imageURL = new URL("http://www.sys-con.com/java/covers/currentcoversmall.jpg");
java.awt.Image img =
this.getImage(imageURL);

You can compress this as follows:

Image img = this.getImage(new
URL("http://www.sys-con.com/java/covers/currentcoversmall.jpg "));

The getImage() method is provided by java.applet.Applet. The URL class is provided by java.net.URL. Be sure to import it.

Code and Document Bases
If you don't know the exact URL of the image, but you do know its name and that it's in the same directory as the applet, you can use an alternate form of getImage() that takes a URL and a filename.

Use the applet's getCodeBase() method to return the URL to the applet directory like this:

Image img =
this.getImage(this.getCodeBase(),
"test.gif");

The getCodeBase() method returns a URL object that points to the directory where the applet came from.

Finally, if the image file is stored in the same directory as the HTML file, use the same getImage() method but pass it getDocumentBase() instead. This returns a URL that points at the directory that contains the HTML page in which the applet is embedded.

Image img =
this.getImage(this.getDocumentBase(),
"test.gif");

If an image is loaded from the Internet, it may take some time for it to be fully downloaded. Most of the time you don't need to worry about this. You can draw the image as soon as you've connected it to a URL using one of the above methods. Java will update it as more data becomes available without any further intervention on your part.

Load all the images your applet needs in the init() method. In particular, you don't want to load them in the paint() method. If you do they will be reloaded every time your applet repaints itself, and applet performance will be abysmal.

Drawing Images at Actual Size
Once the image is loaded, draw it in the paint() method using the drawImage() method, like this:

g.drawImage(img, x, y, io)

"img" is a member of the Image class that you should have already loaded in your init() method. "x" is the x coordinate of the upper left-hand corner of the image; "y" is the y coordinate of the upper left-hand corner. "io" is a member of a class that implements the ImageObserver interface.

The ImageObserver interface is how Java handles the asynchronous updating of an image when it's loaded from a remote Web site rather than directly from the hard drive. The phrase java.applet.Applet implements Image Observer, so for now just pass the keyword for this to drawImage() to indicate that the current applet is the ImageObserver that should be used.

A paint() method that does nothing more than draw an image starting at the upper left-hand corner of the applet may look like this:

public void paint(Graphics g) {
g.drawImage(img, 0, 0, this);
}

This draws the image of the actual size of the picture.

Scaling Images
You can scale an image into a particular rectangle using this version of the drawImage() method:

public boolean drawImage(Image img,
int x, int y, int width,
int height, ImageObserver io)

The code terms "width" and "height" specify the size of the rectangle to scale the image into. All other arguments are the same as before. If the scale is not in proportion to the size of the image, it can end up looking quite squashed.

To avoid disproportionate scaling, use the image's getHeight() and getWidth() methods to determine the actual size, then scale appropriately. For instance, this is how you would draw an image scaled by one-quarter in each dimension:

g.drawImage(img, 0, 0,
img.getWidth(this)/4,
img.getHeight(this)/4, this);

This program reads a GIF file in the same directory as the HTML file and displays it at a specified magnification. The name of the GIF file and the magnification factor are specified via PARAMs (see Listing 1).

This applet is straightforward. The init() method reads two PARAMs, the name of the image file and the magnification factor. The paint() method calculates the scale and then draws the image.

You may ask why the scale factor is calculated in the paint() method rather than the init() method. Some time could be saved by not recalculating the image's height and width every time the image is painted. After all, the image size should be constant.

In this application the size of the image doesn't change, and indeed it will be a rare image that changes size in the middle of an applet. However, in the init() method the image probably hasn't fully loaded.

If you were to try the program below, which does exactly that, you'd see that the image wasn't scaled at all. The reason is that in this version the image hasn't loaded when you make the calls to getWidth() and getHeight(), so they both return -1 (see Listing 2).

Color
Color is a class in the AWT. Individual colors like red or mauve are instances of this class, java.awt.Color. Be sure to import it if you want to use other colors than the default ones.

Create new colors using the same RGB triples that you use to set background colors on Web pages. However, use decimal numbers instead of the hex values used by the bgcolor tag. For example, medium gray is Color(127, 127, 127), pure white is Color(255, 255, 255), pure red is (255, 0, 0), and so on.

As with any variable you should give your colors descriptive names. For instance:

Color medGray = new Color(127, 127, 127);
Color cream = new Color(255, 231, 187);
Color lightGreen = new Color(0, 55, 0);

A few of the most common colors are available by name. Some of these are Color.black, Color.cyan, Color.gray, Color.lightGray, Color.magenta, Color.red, and Color.yellow

Color is not a property of a particular rectangle, string, or other thing you may draw. Rather, color is a part of the Graphics object that does the drawing. To change colors you change the color of your Graphics object. Then everything you draw from that point forward will be in the new color, at least until you change it again.

When an applet starts running, the color is set to black by default. You can change this to red by calling g.setColor(Color.red), then change it back to black by calling g.setColor(Color.black). The following code fragment shows how you'd draw a pink string followed by a green one:

g.setColor(Color.pink);
g.drawString("This String is pink!", 50, 25);
g.setColor(Color.green);
g.drawString("This String is green!", 50, 50);

Remember, everything you draw after the last line will be drawn in green. Therefore, before you start messing with the color of the pen, it's a good idea to make sure you can go back to the color you started with. For this purpose Java provides the getColor() method. Use it as follows:

Color oldColor = g.getColor();
g.setColor(Color.pink);
g.drawString("This String is pink!", 50, 25);
g.setColor(Color.green);
g.drawString("This String is green!", 50, 50);
g.setColor(oldColor);

System Colors
In Java 1.1, the java.awt.SystemColor class is a subclass of java.awt.Color, which provides color constants that match native component colors. For example, if you wanted to make the background color of your applet the same as the background color of a window, you might use this init() method:

public void init {
this.setBackGround(SystemColor.window);
}

These are some of the available system colors:

  • SystemColor.desktop:  Background color of desktop
  • SystemColor.activeCaption:  Background color for captions
  • SystemColor.activeCaptionBorder:  Border color for caption text
  • SystemColor.inactiveCaptionText:  Text color for inactive captions
  • SystemColor.window:  Background for windows
  • SystemColor.windowBorder:  Color of window border frame
  • SystemColor.menu:  Background for menus
  • SystemColor.menuText:  Text color for menus
  • SystemColor.text:  Background color for text
  • SystemColor.textHighlight:  Background color for highlighted text
  • SystemColor.textHighlightText:  Text color for highlighted text
  • SystemColor.controlText:  Text color for controls
  • SystemColor.controlHighlight:  Highlight color for controls
  • SystemColor.controlShadow:  Shadow color for controls
  • SystemColor.inactiveControlText:  Text color for inactive controls
  • SystemColor.info:  Background color for spot-help text

    Fonts
    You've already seen one example of drawing text in the HelloWorldApplet program in Part 1. You call the drawString() method of the Graphics object. This method is passed the string you want to draw as well as an x and y coordinate.

    If g is a Graphics object, then the syntax is:

    g.drawString(String s, int x, int y)

    The string is simply the text you want to draw. The two integers are the x and y coordinates of the lower left-hand corner of the string. The string will be drawn above and to the right of this point. However, letters with descenders like y and p may have their descenders drawn below the line.

    Until now all the applets have used the default font, probably some variation of Helvetica, though this is platform-dependent. However, unlike HTML, Java does allow you to choose your fonts. Java implementations are guaranteed to have a serif font such as Times New Roman that can be accessed with the name "Serif," a monospaced font like Courier that can be accessed with the name "Mono," and a sans serif font like Helvetica that can be accessed with the name "SansSerif."

    The following applet lists the fonts available on the system it's running on. It does this by using the getFontList() method from java.awt.Toolkit. This method returns an array of strings containing the names of the available fonts. These may or may not be the same as the fonts installed on your system. It's implementation-dependent whether or not all the fonts a system has are available to the applet (see Listing 3).

    Choosing Font Faces and Sizes
    Choosing a font face is easy. First create a new Font object, then call g.setFont(Font f). To instantiate a Font object use this constructor:

    public Font(String name, int style, int size)

  • Name:  Name of the font family, e.g., "Serif," "SansSerif," or "Mono."
  • Size:  Size of the font in points. In computer graphics a point is considered to be equal to 1 pixel: 12 points is a normal-size font; 14 points is probably better on most computer displays. Smaller point sizes look good on paper printed with a high-resolution printer, but not in the lower resolutions of a computer monitor.
  • Style:  A mnemonic constant from java.awt.Font that tells whether the text will be bold, italic, or plain. The three constants are Font.PLAIN, Font.BOLD, and Font.ITALIC.

    The program in Listing 4 prints each font in its own face and 14-point bold.

    FontMetrics
    No word wrapping is done when you draw a string in an applet, even if you embed new lines in the string with \n. If you expect that a string may not fit in the applet, you should probably use a TextArea component instead. You'll learn about text areas and other AWT components in a later article.

    However, there are times when you will need to concern yourself with how much space a particular string will occupy. You find this out with a FontMetrics object. FontMetrics allows you to determine the height, width, or other useful characteristics of a particular string, character, or array of characters in a particular font.

    As an example, the program in Listing 5 expands on the DrawString applet. Previously, text would run off the side of the page if the string was too long to fit in the applet. Now the string will wrap around if necessary.

    To tell where and whether to wrap the string, you need to measure the string, not its length in characters - which can be variable - but rather its width and height in pixels. Measurements of this sort on strings clearly depend on the font that's used to draw the string. All other things being equal, a 14-point string will be wider than the same string in 12- or 10-point type. To measure character and string sizes, you need to look at the FontMetrics of the current font.

    To get a FontMetrics object for the current Graphics object, use the java.awt.Graphics.getFontMetrics() method. From java.awt.FontMetrics you'll need fm.stringWidth(String s) to return the width of a string in a particular font, and fm.getLeading() to get the appropriate line spacing for the font.

    There are many more methods in java.awt.FontMetrics that let you measure the heights and widths of specific characters as well as ascenders, descenders, and more, but these three methods will be sufficient for this program.

    Finally, you'll need the StringTokenizer class from java.util to split up the string into individual words. However, you do need to be careful lest some annoying beta tester (or, worse yet, end user) tries to see what happens when they feed the word antidisestablishmentarianism or supercalifragilisticexpialidocious into an applet that's 50 pixels across.

    Next Month
    This should be enough to keep you busy for now. Next month you'll learn how to add animation to your applet.

    Author Bio
    Bob Hendry is a PowerBuilder instructor for Envision Software Systems and a frequent speaker at both national and international PowerBuilder conferences. He specializes in PFC development and has written two books on the subject, including Programming with the PFC 6.0. He can be contacted at bobh@envisionsoft.com.

    About Bob Hendry
    Bob Hendry is a PowerBuilder instructor for Envision Software Systems and a frequent speaker at national and international PowerBuilder conferences. He specializes in PFC development and has written two books on the subject, including Programming with the PFC 6.0.

  • PBDJ LATEST STORIES . . .
    3rd International Virtualization Conference & Expo: Themes & Topics
    From Application Virtualization to Xen, a round-up of the virtualization themes & topics being discussed in NYC June 23-24, 2008 by the world-class speaker faculty at the 3rd International Virtualization Conference & Expo being held by SYS-CON Events in The Roosevelt Hotel, in midtown
    The PB Future: More on Graphs in PowerBuilder 11.5
    Last week I posted a screen shot of the new 3D Rendering capabilities being added to some of the 3D graphs in PowerBuilder 11.5. It was met with mixed reviews on the PowerBuilder Futures newsgroup (forums.sybase.com) so I went back to the drawing board to see what I could come up with.
    BluePhoenix Expands Modernization Collaboration with Microsoft
    BluePhoenix announced that it has expanded its collaboration with Microsoft on legacy modernization projects. The collaboration provides customers moving their applications or databases to .NET-based environments the best in both modernization services and technical support. BluePhoeni
    Sybase PowerBuilder Delivers AJAX and .NET Enhancements Enabling Rich Internet Application Development
    Sybase announced that AJAX development capabilities and further Microsoft .NET enhancements have been added to the latest version of Sybase PowerBuilder 11, the premier 4GL rapid application development (RAD) tool. PowerBuilder 11.2 represents another milestone in the PowerBuilder road
    PowerBuilder 11.2 Released: Sybase's Flagship IDE
    Sybase has released the production version of its flagship .NET development tool - PowerBuilder version 11.2. This latest release of its premier IDE for RAD includes not only standard fixes but also a good list of new features. Here is the 'Coles Notes' version of these new features.
    PowerBuilder Takes You To .NET
    In June of 2007, Sybase released PowerBuilder 11. PowerBuilder developers can now deploy PowerBuilder components as .NET Assemblies or as .NET Web Services. A PowerBuilder developer can now create these .NET resources so that those who develop .NET solutions can benefit from PowerBuild
    SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
    SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
    Click to Add our RSS Feeds to the Service of Your Choice:
    Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
    myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
    Publish Your Article! Please send it to editorial(at)sys-con.com!

    Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

    SYS-CON FEATURED WHITEPAPERS

    ADS BY GOOGLE
    BREAKING POWERBUILDER / SYBASE NEWS
    Sybase and Sun Set Guinness World Record for World's Largest Data Warehouse
    Sybase, Inc. (NYSE:SY), the largest enterprise software and services company exclusively