Wednesday, 13 May 2015

Drawing in Java

  The methods and tools described in this section enable you to draw simple graphical items that are non-interactive-although you can use the Canvas component and/or the location of mouse clicks to make these items behave as though they were interactive. If you've ever written code for a modern GUI, or even Windows, you'll find most of the drawing utilities fairly familiar. All these operations are implemented as methods on the Graphics class. Because anything you can draw on has a Graphics class as an attribute, this doesn't limit the utility of these functions.

Drawing Text

You've already seen an example of drawing text using the drawString method. The general syntax for that method follows:
Graphics g;
g.drawString(String string_to_draw, int x_position, int y_position)
You also can use the drawChars method if you have an array of type char rather than a string.

Working with Fonts

Back in the dark ages, before the Mac and the desktop publishing revolution, people were used to having only a few fonts available for use on the computer. Things have changed dramatically since then; now people commonly buy CD-ROMs with more than 1,000 fonts for $50. Unfortunately, Java reintroduces a new generation to the wonders of limited fonts. This probably will change rapidly as Java and the Internet standards mature, but for right now, typographic simplicity is the order of the day.
You can create instances of the Font class using this creator syntax:
Font a_font = new Font(String name_of_font, int font_style, int font_size);
The generally available fonts follow:
Courier
Dialog
Helvetica
Symbol
TimesRoman
Because the set of available fonts may change, you might want to use a variation of the applet shown in Listing 17.6 to check for what fonts are available; this code works in applications as well.

Listing 17.6. Checking for available fonts.
import java.awt.*;
import java.applet.Applet;


public class discover_fonts extends Applet
{

    public void paint(Graphics g){
        String FontList[];
        int i;
        Font a_font;

        FontList = getToolkit().getFontList();
        for(i=0;i<FontList.length;i++) {
            a_font = new Font(FontList[i],Font.BOLD,12);
            g.setFont(a_font);
            g.drawString("This is the " + FontList[i] +
                     " Font",25, 15*(i + 1));
        }
    }
}

This applet just gets a list of strings containing the names of the available fonts.

The last line is Symbol font. The style for all the fonts was set to bold by using the font constant Font.BOLD. You also can use Font.ITALIC and Font.PLAIN. You can combine styles by bitwise ORing them. This line produces a font that is both italic and bold, for example:
Font a_font = new Font("Helvetica",(Font.BOLD | Font.ITALIC),12);

Note
Not all fonts support all styles. Courier prints the same no matter what you set the style to, as you can see in Figure 17.7.

Measuring Fonts, Centering Text


You'll find that you often need to precisely position text in an applet. The FontMetrics class provides an easy way to find out how much space text drawn with a given instance of Font will be. Just in case you're not a typographic expert, Table 17.1 provides some quick definitions of the key font measurement terms, illustrated in Figure



Listing 17.7. Accessing FontMetrics information.
import java.awt.*;
import java.applet.Applet;


public class font_metrics extends Applet
{

    public void paint(Graphics g){
        Font a_font;
        FontMetrics a_font_metric;
        String the_message;
        int string_width, font_height,font_ascent, font_descent;
        int font_ascent_no_white, font_descent_no_white;
        int y;

        the_message = "Alien Space Monsters! ";
        //Make a new font
        a_font = new Font("Helvetica",Font.BOLD,16);
        g.setFont(a_font);
        //get the metrics for the font
        a_font_metric = g.getFontMetrics();
        //get the width of the message
        string_width = a_font_metric.stringWidth(the_message);
        //get the height of the font
        font_height = a_font_metric.getHeight();
        //get the ascent of the font; this includes whitespace
        //recommended by the font designer
        font_ascent = a_font_metric.getAscent();
        //get the descent of the font; this includes whitespace
        //recommended by the font designer
        font_descent = a_font_metric.getDescent();
        //get the ascent without whitespace
        font_ascent_no_white = a_font_metric.getMaxAscent();
        //get the descent without whitespace
        font_descent_no_white = a_font_metric.getMaxDescent();
        //now show these values to the user
        y = 10;
        g.drawString(the_message, 10,y);
        y += font_height + 1;
        g.drawString("Message width is " + string_width, 10,y);
        y += font_height + 1;
        g.drawString("Font height is " + font_height, 10,y);
        y += font_height + 1;
        g.drawString("Font ascent is " + font_ascent +
            " without white space it's " + font_ascent_no_white , 10,y);
        y += font_height + 1;
        g.drawString("Font descent is " + font_descent +
            " without white space it's " + font_descent_no_white , 10,y);

    }
}

This information is useful in a number of ways. First, notice how the tops of the letters in the first line in Figure 17.9 are cut off. That's because when you specify the y coordinate for a string, you're specifying the location of the baseline-not the upper-left corner of the text that is being drawn. To figure out where to put the baseline, you just need to look at the value of the ascent. Instead of defining the first value of y as 10, just change it to this:

y = font_ascent + 2; //the extra 2 provides some whitespace
                     //that the font otherwise lacks

nother common use for FontMetrics data is to center text in an area. The code in Listing 17.8 centers text in an area.

Listing 17.8. Centering text.
    public void draw_centered_text(Graphics g, String the_msg,
                                     int width, int height) {
        int x,y;
        FontMetrics fm;

        fm = g.getFontMetrics();
        //find out how much free space there is on either side of the string by
        //subtracting the width of the string from the width of the window and
        //dividing by 2
        x = (width - fm.stringWidth(the_msg))/2;
        //find out how much free space there is above
        //and below the string's baseline
        y = fm.getAscent() + (height - fm.getHeight())/2;
        //draw the string so that the baseline is centered
        g.drawString(the_msg,x,y);
    }


Note
You can get the width and height of an applet's area by using the getSize method, which returns a Dimension value. The height() and width() methods of the Dimension class enable you to get the height and width values.


No comments:

Post a Comment