Java Graphics    
Peter Komisar   ©
  Conestoga College     
latest version  5.72  /  2010


Java Graphics Overview


Pixel - 'picture element'

Most visual programming environments will provide a
library of visual components to allow a programmer to
assemble Graphical User Interfaces.  We have looked
at Java's AWT and Swing components. These visual
components themselves have to be 'painted' using low-
level graphics calls on the underlying system.

If we consider what goes into a visual component like a
button we will see there is a border with a few pixels of
width and height. Inside the border usually a title will be
drawn. More elaborate presentations may include other
graphical enhancements. Another important part of the
visual presentation of a component is some change we
associate with the component being activated.

The GUI Drawing Methods Are Available For Custom Graphics

The same collection of graphical method calls that are
used by component designers to build visual components
have been made available to the Java developer. These
functions can be used to customize the appearance of
supplied components or to create other graphical displays
such as animations.


Graphics Work at the Pixel Level

Graphics as a topic looks at how pixels are rendered
on the screen. Graphics includes a discussion of color,
since each pixel rendered can always be described in
terms of a color value. Fonts and font metrics are also
related to the general discussion of drawing to screen.
Images are also related to graphics which we treat as
a separate topic in the next note.
 

The Mechanics of Rendering Images   // the Graphics class

The tasks of drawing the various components in Java is
handled for the most part by the Graphics class. From
the developer's point of view it can be treated as just
another class described in the Java library.

The Graphics Context

 When referenced from a method, the graphics object is
often referred to as the 'graphics context'. This alludes to
the fact that when it comes to graphics most of the calls
reach down and use drawing tools provided by the native
platform.

// Graphics context: based on native calls on underlying system.

On a Mac, the Java environment is reaching into the Mac
toolkit and rendering lines and rectangles the same way
a developer working for Apple would make the calls. The
same would be true for the Windows or Linux platforms.


You never instantiate the Graphics class. The Graphics
object is made available to you, as you have seen in the
paint method of the Applet 'Hello World' example. We
bring forward the example below.

// Graphics class is not instantiated, and is supplied as in the paint( ) method

Hello World in an Applet Code Sample

// <applet code="OK.class" width ="600" height="300"></applet>

import java.awt.*;
import java.applet.*;

public class OK extends Applet{
   public void paint( Graphics g){
     g.setFont(new Font("Monospaced", Font.BOLD, 22));
     g.drawString("OK, It's Hello World!", 50, 60 );
   }
}


The Event Thread a.k.a the GUI Thread a.k.a. the Graphics Thread

Earlier we saw that a separate thread takes care of
processing events. This is the same thread that takes

care of painting GUIs and thus is also called the GUI
thread. This includes custom graphics.

Component Class Methods, repaint( ), update( ) & paint( )

The GUI thread accomplishes it's painting tasks by calling
a set of methods at regularly timed intervals and also
whenever a special need arises. such as when a container
is re-sized or a visual panel covers another panel.

The repaint, update and paint methods are all defined
in the top-level Component class where they can apply
to the whole family of  components. They are called in
order. The repaint( ) method calls update( ). The update( )
method calls paint( ).

// repaint( ) calls update which calls paint( ) by default every 100 ms

The repaint( )  method schedules calls to update every
100 milliseconds by default. The update( )
method takes
care of clearing a screen, essentially, by repainting the
entire surface of
the given component with a rectangle
that is set to whatever to the background color.
 

Once the background is repainted, update( ) calls paint( ) 
to render the screen with
whatever graphics are described
in the paint method. This sounds like a lot of painting

and it is, but it is just a reflection of the dynamic way all
images are presented on
computer monitors where the
screen is refreshed constantly by the electron guns
firing
electrons at the phosphors on a screens inner surface or
more recently activating plasma, LCD and LED pixels.


The Methods that Render Java Visual Elements to Screen
 

void repaint( )          

repaint( ) puts to screen any changes that have been made to a visual element's state or appearance. The  repaint( ) method schedules calls to update( ), on most systems, every 100 milliseconds

void update
(Graphics g)

provides a convenient entry point to participate in window painting The default  is to clear a component's area to the background color then call paint( )

void paint
(Graphics g)

paint( ) can be overridden to dynamically change the display



All Component's Share the paint( ) Method


When studying the Applet class, we saw the paint( ) function
overridden to
control how a component was rendered on screen.
Applet's paint( ) method is the same
paint that we see here which
is part of this general painting mechanism used by all the visual

components.

repaint( )

The repaint( ) method may be called explicitly. Generally it has little
effect as repaint( ) is always being called anyway. Sometimes it can
be used to ensure a change updates immediately for instance, to
change text on a GUI's label.
The method forces an immediate
repaint.

// sometimes useful to force an immediate change on a static element

The repaint( ) method is handy because it doesn't require a Graphics
context like update( ) and paint( ) and so is easy to introduce into GUI
code.

The method is defined in several overloaded forms. The other forms
allow restricting the
area that repainting and the maximum amount of
time that transpires  before a repaint is
made.

// repaint( ) comes in overridden forms and may be called explicitly


update( )

The update( ) method is often overridden to reduce flicker. We will see
this technique a little
later. The basic strategy to do this is to eliminate
painting the background.  This approach when used to do drawings,
will allow any changes made to a drawing remain on screen. Following
is the default form of the update( ) method. The background fills are
mainly responsible for flicker.

With today's really fast computers, flicker wasn't the concern it use to be.

// if necessary the background could be made black


Default Form of the update( ) Method

public void update(Graphics g){
     g.setColor(getBackground( ));
     g.fillRect( 0, 0, width, height);
     g.setColor(getForeground( ));
     paint(g);
     }

The following overridden version of the method shows the background
fills deleted.

Overridden Form of the update( ) Method to Reduce Flicker

public void update(Graphics g){
      paint(g);
     }

// with same size images this form reduces flicker
// with drawing it allows changes to accumulate

Here is a short code sample to demonstrate the effect of overriding
update so the background is not cleared.


Code Sample

import javax.swing.*;
import java.awt.*;

class Quick extends JFrame{
      Quick(){
             add(new Pane());
             setSize(600,600);
             setVisible(true);
             }
 
public static void main(String[] args){
       new Quick();
      }
}

class Pane extends Panel{

// we include a a preview of a Color constructor that has a
// value for opacity. Opacity variations are demonstrated
when
// the overridden version of update is used so that
colors combine


  public void paint(Graphics g){

      g.setColor(new Color((int)(Math.random()*255),
                           (int)(Math.random()*255),
                           (int)(Math.random()*255),
                           (int)(Math.random()*255)
                          )
                );
      
      g.fillOval((int)(Math.random()*600),
                 (int)(Math.random()*600),
                 60,50);
      
    try{
       Thread.sleep(800);
       repaint( );
      
   // a 'cheat' to get looping
       }
    catch(InterruptedException ie)
       {
       }
     }

 /*
   // uncomment the overridden update( ) method
   // this form doesn't clear background
    
   public void update(Graphics g){
        paint(g);
        }
  */

paint( )

The paint( ) method is the workhorse for presenting graphics.
It provides a graphics
context reference that may be used to
call the various drawing methods available in the
Graphics
class. We see later in the note how the graphics context can
also be cast to the 2DGraphics object
making available the more
sophisticated drawing methods of the 2D class.

The paint method is the right place to put your custom drawings
as paint is always
called at the appropriate times, whenever
 visual changes need to be made. 

// paint( ), where custom graphics are executed
 


The Color, Font & Graphics Classes



If the Graphics class is the principle actor on Java's visual
stage, important supporting
roles are provided by the Color,
Font and Image classes. We look at the first two next.


The Color Class                 


Class Color is in the 'java.awt' package. Java uses the RGB
model to compose colors
from red, green and blue components.
The vividness of each color can be described using three bytes,
one for each color where the integer value, 0 is darkest and
255 is brightest.

The Color class constructors also allows these colors to be
created from float values or a single int containing all three
color values. Color class also provides static fields for each
color such as Color.blue (or uppercase, Color.BLUE). These
constants are convenient when a simple
color is needed.
The static fields are blue, cyan, darkGray,
gray, green,
lightGray, magenta, orange, pink, red, white and yellow.
Older Canadians may note that the American spelling of
'grey', that is, 'gray' is used in Java.

// note English 'grey' is spelled American, 'gray'

Static Color Constant Example

Color.BLACK // same as Color.black


The following table shows the Color class constructors.


Color Class Constructors

Color
(float r, float g, float b)

Creates an opaque sRGB color with the specified red, green, and blue values in the range  (0.0 - 1.0).

Color
(float r, float g, float b, float a)
Creates an sRGB color with the specified red, green, blue, and alpha values in the range  (0.0 - 1.0).
Color(int rgb) Creates an opaque sRGB color with combined RGB value consisting of the red component in bits 16-23, the green in bits 8-15, and the blue in bits 0-7.

Color
(int rgba, boolean hasalpha)

Creates an sRGB color with the specified combined RGBA value consisting of the alpha component in bits 24-31, the red component in bits 16-23, the green in bits 8-15, and the blue in bits 0-7.
Color
(int r, int g, int b)
Creates an sRGB color with the specified red, green, blue, and alpha values in the range (0 - 255).
Color
(int r, int g,
int b, int a )
Creates an sRGB color with the specified red, green, blue, and alpha values in the range (0 - 255).
Color(ColorSpace
cspace,
float[ ]
components,
float alpha)
Creates a color in the color space of the supplied ColorSpace with the color components specified in the float array and the specified alpha.



Color Class Constructors

The HSB Model

The HSB model uses hue, saturation and brightness to
desc
ribe colors and is not directly supported by Java in
constructors. Java does supply methods that allow
conversion between the two color systems.


Method that Converts Colors between RGB and HSB systems

static int HSBtoRGB
(float hue, float saturation, float brightness)
    // Converts HSB Color component to equivalent RGB values

static float[ ]
RGBtoHSB (int r, int g, int b, float[ ] hsbvals)
  // Converts RGB Color component to equivalent HSB values


Example

import java.awt.Color;

class Convert{
 public static void main(String[] args){
   float[] hsb =new float[]{0.0f,0.0f,0.0f};
   hsb= Color.RGBtoHSB(122, 222,97,null);
  
     for (int i=0;i<3;i++){
         System.out.println(hsb[i]);
         }
    }
}  

OUTPUT

>
0.29999998
0.5630631
0.87058824


Transparency                              
      

An additional 'alpha' component describing a pixel's  transparency
can be included with
the RGB model. This value is supplied to the
Color constructors
. The following example shows how the bits of an
int value may be used to carry an alpha value which describes
transparency and red, green and blue values.

Alpha Red Green Blue Bit Mapping

| alpha bits  31 - 24 | red bits  23 - 16 | green bits  15 - 8 | blue bits  7 - 0 |


An alpha value of 0 is totally transparent while a value of 255 is a solid
color.
Values between are said to vary in translucence or opacity.

It may be noted that the Color constructor that has four ints, three for red,
green and blue and the last for transparency seems out of order with respect
to how the values are loaded into an int above, but that is just the way the
Java authors decided to define this particular constructor.

Following is a code sample that shows the transparency value being used.


Color Transparency Example

import javax.swing.*;
import java.awt.*;


class ABC extends JFrame{
      ABC(){
             add(new Pane());
             setSize(600,600);
             setVisible(true);
             }
 
public static void main(String[] args){
       new ABC();
      }
}

class Pane extends Panel{
      Pane( ){
         setBackground(Color.BLACK);
         }

  public void paint(Graphics g){

      g.setColor(new Color(255,0,0,125));     
      g.fillOval(200,100,200,200);
      g.setColor(new Color(0,255,0,125));     
      g.fillOval(275,200,200,200);
      g.setColor(new Color(0,0,255,125));     
      g.fillOval(125,200,200,200);     
      }    
}


 Color Class Methods

The following table shows most of the color class methods. Among
others, there
are convenience brighter( ) darker( ) methods that can
be used in rollover effects,
information retrieving methods and methods
to convert to and from the HSB model.

Color Class Methods 

 Color brighter( )  Creates a brighter version of this color.
 Color darker( )  Creates a darker version of this color.
 static Color
 decode(String nm)
 Converts a String object to an integer and
 returns
the specified opaque color.
 boolean equals(Object obj)  Determines whether an object is equal to this color.
 int getAlpha( )  Returns the alpha component.
 int getBlue( )   Returns the blue component.
 static Color
 getColor(String nm) 
 Finds a color in the system properties. 
  // one of three getColors
 int getGreen( )  Returns the green component.
 static Color getHSBColor
 (float h, float s, float b)
 Creates a Color object based on values supplied 
 for the HSB  color model.
 int getRed( )  Returns the red component.
 int getRGB( )  Returns the RGB value representing the color in the default RGB ColorModel.
 float[] 
 getRGBColorComponents
 (float[] compArray)
 Returns a float array containing the color components (no alpha) of the Color, in the
default sRGB color space.
 float[] getRGBComponents
  (float[] compArray)
 Returns a float array containing the color and alpha components of the Color, as represented in the default sRGB color space.
 int getTransparency( )  Return the transparency mode for this Color.
 int hashCode( )  Computes the hash code for this color.
 static int HSBtoRGB
 (float hue, float saturation,
 float brightness)
 Converts the components of a color, as specified by  the HSB model, to an equivalent set of values for the default RGB model.
static float[]
RGBtoHSB
 (int r, int g, int b,
 float[] hsbvals)
 Converts the components of a color, as specified by the default RGB model, to an equivalent set of values  for hue, saturation, and brightness, the components of the HSB model.
 String toString( )  Returns a string representation of this color.



The following class called GetColors, uses the get methods to show
the red, green blue components of the stock Color class constants. The
command line output together with the visual component presentation
of the various colors form complementary views of the same information.

This code is a bit tedious in it's long hand form and might have
benefited from the loop treatment which was used in the next example.


Getting the Red Green Blue Components of the Stock Color Set

/* A class to get the red green blue values of the base set of colors. */

import java.awt.*;

class GetColors{
GetColors(){
int r,g,b;

System.out.println
("Red, Green Blue Components of Stock Colors");
System.out.println
("==========================================");

r=Color.blue.getRed();
g=Color.blue.getGreen();
b=Color.blue.getBlue();
System.out.println("blue: "+r +" "+ g +" "+ b);

r=Color.cyan.getRed();
g=Color.cyan.getGreen();
b=Color.cyan.getBlue();
System.out.println("cyan: "+r +" "+ g +" "+ b);

r=Color.darkGray.getRed();
g=Color.darkGray.getGreen();
b=Color.darkGray.getBlue();
System.out.println("darkGray: "+r +" "+ g +" "+ b);

r=Color.gray.getRed();
g=Color.gray.getGreen();
b=Color.gray.getBlue();
System.out.println("gray: "+r +" "+ g +" "+ b);

r=Color.green.getRed();
g=Color.green.getGreen();
b=Color.green.getBlue();
System.out.println("green: "+r +" "+ g +" "+ b);

r=Color.lightGray.getRed();
g=Color.lightGray.getGreen();
b=Color.lightGray.getBlue();
System.out.println("lightGray: "+r +" "+ g +" "+ b);

r=Color.magenta.getRed();
g=Color.magenta.getGreen();
b=Color.magenta.getBlue();
System.out.println("magenta: "+r +" "+ g +" "+ b);

r=Color.orange.getRed();
g=Color.orange.getGreen();
b=Color.orange.getBlue();
System.out.println("orange: "+r +" "+ g +" "+ b);

r=Color.pink.getRed();
g=Color.pink.getGreen();
b=Color.pink.getBlue();
System.out.println("pink: "+ r +" "+ g +" "+ b);

r=Color.red.getRed();
g=Color.red.getGreen();
b=Color.red.getBlue();
System.out.println("red: "+ r +" "+ g +" "+ b);

r=Color.white.getRed();
g=Color.white.getGreen();
b=Color.white.getBlue();
System.out.println("white: "+ r +" "+ g +" "+ b);

r=Color.yellow.getRed();
g=Color.yellow.getGreen();
b=Color.yellow.getBlue();
System.out.println("yellow: "+ r +" "+ g +" "+ b);
 }
public static void main(String[] args){
 new GetColors();
 }
}

Displaying the Stock Color Set

The following code sample displays the different colors
that are part of the stock set of Java colors.


Color Class Code Sample

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

class Colors extends Frame{
 Colors(){
Label p=null;
setLayout(new GridLayout(3,4));
setBackground(Color.white);
String[] colorArray= new String[]
{"  blue","  cyan","  darkGray","  gray","  green","  lightGray","  magenta",
 "  orange","  pink","  red","  white","  yellow"};

int[][] intArray=new int[][]{ new int[]{0,0,255},new int[]{0,255,255},
                              new int[]{64,64,64},new int[]{128,128,128},
                              new int[]{0,255,0},new int[]{192,192,192},
                              new int[]{255,0,255},new int[]{255,160,0},
                              new int[]{255,170,170}, new int[]{255,0,0},
                              new int[]{255,255,255},new int[]{255,255,0}
                            };

for(int i=0;i<12;i++){
   p =new Label(colorArray[i]);
   p.setBackground(new Color(intArray[i][0],intArray[i][1],intArray[i][2]));
   if(colorArray[i].equals("  darkGray"))
   p.setForeground(Color.white);
   add(p);
   }
setSize(400,400);
setVisible(true);
addWindowListener(new WindowAdapter( ){
    public void windowClosing(WindowEvent e){
       System.exit(0);
       }
    });
}

public static void main(String[] args){
new Colors( );
}
}


The Font & FontMetrics Classes

Following the Color class, the Font and FontMetrics classes
play important supporting
roles in rendering graphics in a
Java program. Fonts
are used to draw text in the Abstract
Windowing Toolkit. Fonts are encapsulated by  the Font class.
The most common Font constructor is shown in the next
example.

Common Font Class Constructor

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


 Example

JLabel label = new JLabel( );
Font font = new Font ("SansSerif ",  Font.ITALIC, 24 );
label.setFont( font );



// The font constructor takes the name of a Font, a value indicating
// whether it is italic, plain or
bold (or a combination of these), and
// the size of the font in pixels


Newer JDK's make available the following fonts.


Newer JDK Default Fonts


Older JDK's called 'Serif' 'TimesRoman' , 'SansSerif' 'Helvetica'
and
'Monospaced'  'Courier'. Calling the deprecated getFontList( )
method on the systems toolkit will
tell you what basic fonts are
available on your system. Though the compiler states the method
is deprecated,
the method call still works.


Example 

String fontnames[] = Toolkit.getDefaultToolkit( ).getFontList( );


Following is a code sample that uses this call. It returns a short list
of fonts that the Java environment maintains. The code sample is
followed by the list it outputs on a  system running the JDK version
1.3.1.

Code using Deprecated getDefaultToolkit( )

public class FontT{
    public static void main(String[] args){
      String fontnames[] = java.awt.Toolkit.getDefaultToolkit( ).getFontList( );
      for(int i=0;i<fontnames.length;i++)
      System.out.println(fontnames[i]);
     }
 }

OUTPUT

C:\NewCode>java FontT

Dialog
SansSerif
Serif
Monospaced
DialogInput

// same list was available on Mandrake Linux 9.2

Following is the suggested replacement code for the deprecated
method shown
above. Using the following code derived the following
extensive list of fonts, returned from the same system used in the
example above running JDK 1.3.1. In order to capture the output
which exceeded a screen, the output is redirected to file with the
line below.

Example    

C:\> java AvailableFonts > FontFile
 

GraphicsEnvironment Code Sample

import java.awt.*;

class AvailableFonts{
 public static void main( String args[ ] ){
  GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment( );
   String [ ] f= ge.getAvailableFontFamilyNames( );
     for(int i=0;i<f.length;i++)
       System.out.println( f[i] );
    }
}

Output 
// Windows 98, JDK 1.3.1, formatted to two columns

Arial,
Arial Black
Arioso
Bedrock
Chevara,

ChevaraOutline
Comic Sans MS
CommonBullets
Conga

Courier New
Dauphin
Default
Dialog
DialogInput
Helmet
HelmetCondensed
Impact, Lucida Bright
Impact, Lucida Bright

Lucida Console
Lucida Sans
Lucida Sans Typewriter
Marlett
Monospaced
SansSerif
Serif
SPW
StarBats
StarMath
Symbol
Tahoma
Times New Roman
Timmons
Verdana
Webdings
Wingdings


Output  // Mandrake Linux 10.x, JDK1.5.0, in a table

A.D. MONO
ActionIs
Adventure
Babelfish
Bazaronite
Beta Dance
Betsy Flanagan
Binary
Bitstream Charter
Bitstream Vera Sans
Bitstream Vera Sans Mono
Bitstream Vera Serif
Blue Highway
Blue Highway Condensed
Brand New
Captain Podd
Century Schoolbook L
Courier
Courier 10 Pitch
Creature
Cursor
Davis
DejaVu Sans
DejaVu Sans
Condensed
DejaVu Sans Mono

DejaVu Serif
DejaVu Serif Condensed

Densmore
der Dämonschriftkegel
Dialog
DialogInput
Die Nasty
Dingbats
DirtyBaker'sDozen
Distortia
Edgewater
Electroharmonix
Eli 5.0b
Embargo
Fadgod
Failed Attempt
FakeReceipt
Flubber
Font in a Red Suit
Fudd
Golden Girdle
Hershey
HydrogenWhiskey
Ikarus
Ikarus Turbulence
Ikarus Vulture
Independence
Indigo Joker

Larabiefont
Lucida Bright
Lucida Sans
Lucida Sans Typewriter
Luxi Mono
Luxi Sans
Luxi Serif
malayalam
Monospaced
Nimbus Mono L
Nimbus Roman No9 L
Nimbus Sans L
Nimbus Sans L Condensed
Raghindi
SansSerif
Serif
Standard Symbols L
URW Bookman L
URW Chancery L
URW Gothic L
URW Palladio L
Utopia

In the exercise you can test Windows XP,  Vista or Windows
7 with JDK 1.5.0 or 1.6.x.  A very impressive list of fonts will
appear.
 
// Mac lists would be interesting too!

Notice if cross platform portability is important you may wish to stick
to the common base internal font types. Otherwise, the systems will
silently supply a default substitute which may not be suitable.

Another approach would be query the system to see if the desired
font was available. If it wasn't a reasonable s
ubstitute based on
internal fonts co
uld be substituted.

// the deprecated method is useful to report the internal fonts for the  system


The Font Class

" A font provides the information needed to map sequences of characters
to sequences of glyphs and to render sequences of glyphs on Graphics
and Component objects. . . .

A glyph is a shape used to render a character or a sequence of characters.
In simple
writing systems, such as Latin, typically one glyph represents one
character. In general,
however, characters and glyphs do not have one-to-one
correspondence

.  . .  the character 'á' LATIN SMALL LETTER A WITH ACUTE, can be represented
by two glyphs: one
for 'a' and one for '´'. On the other hand, the two-character
string "fi" can be represented
by a single glyph, a "fi" ligature.

A font encapsulates the collection of glyphs needed to render a selected set
of characters as well as the tables needed to map sequences of characters
to corresponding sequences of glyphs. "  

                                               _ Quoted From J2SDK1.4.0 Documentation


From the above description see fonts are mappings of character
sets to corresponding sets of shapes called glyphs that can be
drawn on screen to represent the associated character(s).

Font class has increased dramatically in size going from JDK 1.1
to 1.2. It
has expanded from 14 to over 50 methods. The count in
J2SDK 1.4.x was 55 methods and now in JDK 7 it is 57 methods!

The increase comes largely due to Java 2D classes adding features
allowing the fonts to be customized. Looking at the fields in
the next
table alludes to the international character of the Unicode character

set where some sets will use a centered or hanging baseline rather
than the
the Roman baseline where characters stand on top of the
baseline.


Font Class Fields


static int BOLD

The bold style constant.

static int CENTER_BASELINE

The baseline used in ideographic scripts
like Chinese, Japanese, and Korean when laying out text

static int HANGING_BASELINE

The baseline used in Devanigiri and
similar scripts when laying out text
static int ITALIC The italicized style constant.

protected String  name

The logical name of this Font, as passed
to the constructor.

static int PLAIN

The plain style constant.

protected float pointSize

The point size of this Font in float.

static int ROMAN_BASELINE

The baseline used in most Roman
scripts when laying out text

protected int size

The point size of this Font, rounded
to integer.

protected int style

The style of this Font, as passed to
the constructor.


Constructors

There are only two Font class constructors. The less common of the
two takes a Map object containing specified attributes. In practice
the actual object passed in is an object the of Attribute class that
implements the Map interface. This class definition is found in the
java.util.jar package. More specifically, the constructor only recognizes
keys defined in the  class, an Attribute class descendant. So we might
think of the constructor as 'Font(TextAttribute textAttributes) '.

// In practice Font recognizes TextAttribute class keys

We only will concern ourselves with the simpler constructor that
takes a font name, a style and a size parameter.

Constructors

Font(Map attributes)

Creates a new Font with the specified attributes.

Font(String name, int style, int size)

Creates a new Font from the specified name, style  and point size.

Font Methods    // 26 of ~55  methods)
 

 boolean canDisplay
(char c)
Checks if this Font has a glyph for the
specified character.
 int canDisplayUpTo
(char[]
text,
int start,  int limit) 
Indicates whether this Font can display the characters in the specified text starting at
start and ending at limit.
 int canDisplayUpTo
 (String str)
Indicates whether or not this Font can
display a
specified String.
 static Font
 decode(String str)
Returns the Font that the str argument describes.
 Font deriveFont(float size) Creates a new Font object by replicating the current Font object and  applying a new size
to it. // one of five 
 boolean equals(Object obj) Compares this Font object to the specified Object.
 protected void finalize( ) Disposes the native Font object
 Map getAttributes( ) Returns a map of font attributes available
 in this Font
 byte getBaselineFor
  (char c)
 Returns the baseline appropriate for
displaying this
character.
 String getFamily( ) Returns the family name of this Font.
 //one of two
 static Font 
  getFont(String nm)
Returns a Font object from the system properties list.   //one of three
 String getFontName( ) Returns the font face name of this Font.
 // one of two
 float getItalicAngle( ) Returns the italic angle of this Font
 Rectangle2D 
  getMaxCharBounds
  (FontRenderContext frc)
Returns the bounds for the character
 with the maximum
bounds as defined
in the specified FontRenderContext
 String getName( ) Returns the logical name of this Font.
 int getNumGlyphs( ) Returns the number of glyphs in this Font.
 int getSize( ) Returns the point size of this Font, rounded
to an integer.
 float getSize2D( ) Returns the point size of this Font in float
value
 int getStyle( ) Returns the style of this Font.
 AffineTransform 
  getTransform( )
Returns a copy of the transform associated
with this Font.
 int hashCode( )  Returns a hashcode for this Font.
 boolean 
  hasUniformLineMetrics( )
Checks whether or not this Font has
uniform line metrics.
 boolean isBold( )  Indicates whether or not this Font object's
style is BOLD
 boolean isItalic( ) Indicates whether or not this Font object's
style is ITALIC.
 boolean isPlain( ) Indicates whether or not this Font object's
style is PLAIN.
 String toString( ) Converts this Font object to a String representation.

// methods left out relate to GlyphVector & FontRenderContext,
// Line metrics & getStringBounds( )

 

FontMetrics

FontMetrics class returns exact pixel measurements of positions 
and dimensions of text characters. The getLeading( ) method
returns the number of pixels between the maximum descent of
one
line and the maximum ascent of the next line getAscent( )
returns in pixels the distance
from the baseline to the top of most
of the characters in a font getMaxAscent( ) r
eturns in pixels the
distance from the baseline to the top of the tallest character in a
font. The methods of FontMetrics all make better sense after
considering the meanings of the value types these methods return
as shown in the following diagram.
 
// getMaxAscent may return the same value as getAscent( )


FontMetric class provides get methods for each of the
following character measurements;

 

Diagram Showing The Different Aspects Used to Describe Font Metrics

__
__  ^ MaxAscent  - the height of the highest letter in the font set as measured from the baseline
      ^ Ascent - the distance of the average character as measured from the baseline to the character top
__  v Baseline - the base where the average character rests

__  v Descent - the average extension of characters that extend below the baseline like the letter ' y '
__  v MaxDescent - the greatest depth below the baseline reached by any character of the font set

__ ^   Leading is the inter-line gap from theMaxDescent of one line to the MaxAscent of the line below
    v
__
__  ^ MaxAscent     //  Partially repeated to represent the next line below
      ^ Ascent
__  v Baseline         //    "     "       "
__  v Descent
__  v MaxDescent   //    "     "       "
 
The following table lists FontMetric methods and includes the
methods used for obtaining the values described above. With
respect to width information there is a charWidth( ) methods
a getMaxAdvance( ) operation as well as a getMaxCharBounds( )
function.


Partial Summary of FontMetrics Class

Fields
 

protected
Font font

 The actual Font from which the font metrics are created.

Constructor
 

protected
FontMetrics

(Font font) 

Creates a new FontMetrics object for finding height and width info
about the specified Font and specific character glyphs in that Font.


FontMetric Methods 
             
                                  
(15 of 26+ methods)


 

 int bytesWidth
 (byte[] data, 
 int off, int len)

 Returns the total advance width to show the 
 specified array of bytes in this Font.

 int charWidth(char ch) 

 Returns the advance width of the specified 
 character in this Font.  // 1 of  3

 int getAscent( ) 

 Returns the font ascent of the Font described
 by  this FontMetrics object.

 int getDescent( ) 

 Returns the font descent of the Font described 
 by this FontMetrics object.

 Font getFont( )

 Gets the Font described by this FontMetrics object.

 int getHeight( ) 

 Gets the standard height of a line of text in this font.

 int getLeading( )

 Returns the std. leading of the Font described 
 by this FontMetrics object.

 int getMaxAdvance( ) 

 Gets the max. advance width of any character 
 in this Font. 

 int getMaxAscent( )

 Returns the max. ascent of the Font described by 
 this FontMetrics object. 

 Rectangle2D
 getMaxCharBounds
 (Graphics context) 

 Returns the bounds for the character with max. 
 bounds in Graphics context.

 int getMaxDescent( ) 

 Returns the max. descent of the Font described
 by this FontMetrics object.

 int[] getWidths( )

 Gets the advance widths of the first 256 
 characters in the Font.

 boolean 
 hasUniformLineMetrics ( )

 Checks to see if the Font has uniform line metrics.

 int stringWidth
(String str) 

 Returns the total advance width for showing the
 specified String in this Font. 

 String toString( )

 Returns a representation of this FontMetrics 
 object's values as a String.


// see documentation for additional methods


The Graphics Class
  // aka the graphics context

The Graphics class is abstract and largely comprised of abstract
drawing methods. The platform-specific version of the Graphics
class is called the 'graphics context'. The methods of the Graphics
class call a set of native functions defined by the underlying system.

From an applied point of view, the Graphics class is a regular
Java class that drawing methods are called on. The only difference
is you will never call a Graphics class constructor. The graphics
context is most commonly seen as the argument type to the paint( )
method but you can get a graphics context for any component or
image via a call to getGraphics( ) as is shown in the following
example. 

Example

Graphics g = Pic.getGraphics( );

// where Pic may be a  Panel, Image or Canvas


The getGraphics ( ) and dispose(  ) Methods

The getGraphics( ) method is found in several classes
including Component,
PrintJob, Image, BufferedImage,
JComponent, and View.

The dispose( ) method should be used to release graphics
objects when a graphic context is created outside of the
paint( ) method. This frees up system resources and
memory that may be tied up in creating a graphics context.


// if using Graphics outside paint( ) use dispose(  ) to free resources 
 

 2D Graphics


 The Java 2D API gives provides a new toolkit of drawing methods
 that  allow greater
flexibility in the types of graphics that can be
 performed. The Java Tutorial at the Sun
site provides an good
 introduction to the 2D  API, by  D. Adair, J. Ball & M. Pawlan.

 
 To view go to
 http://web2.java.sun.com/docs/books/tutorial/2d/index.html

  
   +--java.awt.Graphics   
             |
// 2D extends Graphics
             +--java.awt.Graphics2D

 Using the 2D class begins with casting the graphics object
 to it's 2D sibling.

public void Paint (Graphics g) {
              Graphics2D g2 = (Graphics2D) g;
              ...
              }
.



Why you should draw in paint( ) and not in action handlers

Java Authors, Heller & Roberts, supply the following reasons
why you should do your painting in the overridden paint method
rather than doing painting in action handler methods.

Maintenance and debugging is easy if all drawing operations
are centrally located. All screen state data is located in one
spot so the screen is rendered accurately and completely.
Finally, painting inside paint( ) ensures repairs are done
consistently in case of screen damage from an overlapping
window.

// draw in paint( ) to make maintenance easy and to screen state is consistent


Graphics Drawing Methods



drawXXX( ) & fillXXX( )

Graphics drawing methods are generally of the form
drawXXX( )
or fillXXX( ) where the former outlines
and the latter fills with a color. A graphics object has
a setColor( ) method that effects the foreground color.
The background color is that of the underlying component.
The default foreground color is black. A fillXXX( ) method
can be used to effect a change in the general background
color.

Most textbooks do a tour of the common drawing methods
so we do the same. Though they are basic , with a little work
they can be used to do sophisticated graphical rendering.

All the methods are declared public and have void return
types. We omit these to keep the bulleted lines shorter.


drawString( )

drawString( ) fills the role for graphics that print( ) does
for System.out.print( ).
The x and y coordinates locate the
beginning of the baseline where the string will be drawn.
For this reason, if you are using the standard Roman
baseline, setting the y coordinate to 0 may put letters
completely off the screen. We can create simple examples
for these methods as
we go and then collect them into a
single sample program.

Example    

g.drawString("A few graphics methods",30,20);

// the default Roman baseline is set with x, y so that the
// letters
appear above it. Coordinate  y set to 0 will put
// many
letters completely out of view.

 

drawBytes( ) & drawChars( )


These methods places length bytes or characters from
offset within data[] to the
point located by (x , y).

Example 

g.drawChars(characters, 2, 3, 10, 240);

// takes char array, at offset 2, for length 3 and draws
// at x, y, coordinates, 10 & 240

 

drawLine( )


drawLine( ) connect two points with a line drawn from
the point described
by x1, y1 to the point at x2, y2.  The
line
is limited to a one pixel width. To workaround this
constraint the fillPolygon( ) c
an be used in it's place to
draw a thicker line or methods found in the Graphics2D
package can be used.

Example   

g.drawLine(30,22,160,22);
 

draw & fillRect( )


These methods can be used to outline or fill a rectangle.
The top left corner of
the rectangle is located at point ( x, y ).
Width extends to the right and height extends so
uth. The
unit
used is pixels. A majority of the graphics methods
build on the approach that
draw and fillRect( ) take, where
the upper left corner is specified along with
the width and
height.

Example   

g.drawRect(30,30,240,140);
 

draw & fill3DRect( )


These  methods provide a convenient way of drawing or
filling a 3D rectangle (similar in appearance to a button) 
If the boolean values raised is true, the
shading makes
the rectangle appear to be elevated , if false, the rectangle

appears depressed. This method likely originated with the
need to make a button look like it is switching state
between dormant and active states.

Example   

g.draw3DRect(250,200,20,30,true);
 

draw & fillOval( )

public void drawOval( int x, int y, int width, int height );
public void fillOval( int x, int y, int width, int height );

The draw and fillOval( ) methods draw an oval inside
the imaginary rectangle described by the width & height
parameters provided to the method. The imaginary
rectangle has
it's top, left corner at the (x,y) coordinate.


Example
        

g.drawOval(40,50,80,20);

draw & fillRoundRect( )


These methods draw or fill rectangles with rounded corners.
arcWidth and arcHeight parameters control diameter of
rounded corners in pixels. You can think
of arc width and
height as the dimension of a rectangle that controls the
shape of a
controlled oval. This oval then is pressed into
the corners of the rounded rectangle.

Example    

g.drawRoundRect(120,50,90,90,80,20);
 

draw & fillArc( )


The draw and fillArc( ) methods continue working with an
oval drawn inside an imaginary rectangle adding a start
angle and an angle of sweep. Only the part of the arc that
is traced from the start angle to the end of the sweep angle
is drawn to screen. A positive sweep value causes a counter
clockwise rotation of the arc.


draw & fillPolygon( )


A polygon is a closed figure with an arbitrary number of
straight sides.
The draw & fillPolygon( ) methods take two
array of points, one for x and one for y values, along with
an int value to specify how many points of the polygon
should be drawn. Specifying different numbers of points
will draw different polygons.

Specifying more points than are defined in the point arrays
results in an ArrayIndexOutOfBounds exception.
Because a
polygon is a closed figure by definition, the first point does
not need to be
repeated.

 
drawPolyline( ) 

drawPolyline(  ) is like drawPolygon except that it is open.
To close a figure with drawPolyline( ), the first and last points
must be the same. There is no fillPolyline( ) as this results in
the same effect that is achieved by fillPolygon( )


Graphics Code Sample

The following code sample shows many of these methods
in use. The applet focuses especially on the how arc width
and height values are used to create the rounded corners
using drawRoundRect( ). Note how the corners have the
shapes corresponding to ovals that would be created if
these values are used.

Graphics Applet Code Sample

import java.applet.*;
import java.awt.*;

  // <applet code="Drawing.class" width="310" height="280"></applet>

public class Drawing extends Applet{
    char[] characters;
    int[] X,Y;
  public void init (){
    characters=new char[]{'A',' ','B',' ','C',' ','D' };
    X=new int[]{20,40,220,250};
    Y=new int[]{210,275,220,270};
    setBackground(new Color(0,0,0));
    setForeground(new Color(255,255,255));
    }

  public void

(Graphics g){
    g.drawString("A few graphics methods",30,20);
    g.drawChars(characters,2,3,55,240); //draws B, space and C
    g.setColor(Color.green);
    g.drawLine(30,22,166,22);
    g.setColor(Color.blue);
    g.drawRect(30,30,240,140);
    g.setColor(Color.lightGray);
    g.draw3DRect(250,200,20,30,true);
    g.setColor(Color.pink);
    g.drawOval(40,50,80,20);
    g.drawOval(70,80,30,70);
    g.setColor(new Color(233,255,233));
    g.drawRoundRect(120,50,90,90,80,20);
    g.drawRoundRect(160,70,90,90,30,70);
    g.setColor(Color.yellow);
    g.drawString("Note how the oval size correspond to",30,190);
    g.drawString("the rounded corners of the rectangles",30,210);
    g.setColor(Color.green);
    g.drawArc(40,210,50,50,140,175);
    g.setColor(Color.gray);
    g.fillArc(190,230,20,20,45,270);
    g.setColor(Color.gray);
    g.drawPolygon(X,Y,4);
    }
  }


Self Test                                                  Self Test With Answers


1) Which of the following statements is not correct?

a) AWT and GUI are different names for the same background thread.
b) The Event thread is separate from the GUI thread and just deals with
    event handling.
c) Java uses the graphics toolkit of each platform the Java virtual machine
    is running on to render graphics.
d) The Graphics context is abstract and therefore cannot be instantiated.
 

2) Which of the following statements is not correct?

a) The GUI thread is also called the Event thread.
b) the methods to render component are all defined in the Container class
c) The GUI thread is responsible for painting and handling events
d) The GUI thread is a background thread like the garbage collector thread.
 

3) Which of the following statements is not correct?

a) A Color can be specified using the dot operator as in Color.darkGray
b) An alpha value of 0 is totally transparent while a value of 255 is a solid color
c)  Java supplies constructors to build colors on both the RGB and HSB models.
d)  HSB stands for hue saturation and brightness.
 

4) Which of the following may be located on, over or under the locations where
     characters are drawn.

a) MaxDescent
b) Leading
c) BaseLine
d) Ascent
 

5) Which of the following would draw a right angle triangle?

int[] x=new int[]{ 50, 50, 100, 100 }
int[] y=new int[]{ 50,100,100, 50 }

a) drawPolyline(x,y,3);
b) drawPolygon(x,y,3);
c) drawPolyline(x,y,4);
d) drawPolygon(x,y,4);
 

6) Select the correct answer. drawOval(150,200, 100, 200); will create an oval

a) whose center is located at the x,y coordinate (150,200) with a horizontal diameter
   of 100 pixels and vertical diameter of 200 pixels
b) bounded by an imaginary rectangle whose center is located at the x,y coordinate
    (150,200) and whose height is 100pixels and width is 200 pixels
c) bounded by an imaginary rectangle whose upper left corner is located at x,y
    coordinates (150,200) and whose height is 100 pixels and whose width is 200 pixels
d) bounded by an imaginary rectangle whose upper left corner is located at x,y
    coordinates (150,200) and whose height is 200 pixels and whose width is 100 pixels


Exercise         



1.(i) Find out what fonts your computer has by calling the static
getDefaultToolkit( ) on the Toolkit class. (Remember it returns a
String array which you'll have to print to screen, say using a for
loop set to iterate for the stringArray.length) When you build your
simple class with a main method as it's first line you'll also have
to import java.awt.* where Toolkit class resides.

(ii) You'll notice the compiler tells you this method is deprecated.
Run the program with the -deprecation option to see what the
compiler says.

(iii) Repeat the exercise using the code sample from the notes
containing the GraphicsEnvironment references. What are the
differences in the fonts returned by the two techniques?

2. Look at the result of running the Colors program code example.
In reference to the three integer values returned for each color;

(i) What do the colors red green blue have in common?
(ii) What general formula can you use to describe the r g b numbers
that yield the various shades of gray. 

// in mathematical terms or as a simple verbal description

3. Create arrays of x and y coordinates for five points. Draw a
polygon using this array specifying 3, 4 and 5 points. What do
you observe for each?

4. Using Color, Font and Graphics create an art applets to appear
on a HTML page for 'The Maple General Store'. Use three different
font types and sizes.

// really aiming to use draw or fill Polygon( ) to draw a maple leaf