Sunday 26 March 2017

Working with Color, Setting the Paint Mode & Working with Fonts - Java Tutorials

Working with Color

Java supports color in a portable, device-independent fashion. The AWT color system allows you to specify any color you want. It then finds the best match for that color, given the limits of the display hardware currently executing your program or applet. Thus, your code does not need to be concerned with the differences in the way color is supported by various hardware devices. Color is encapsulated by the Color class.

Color defines several constants (for example, Color.black) to specify a number of common colors. You can also create your own colors, using one of the color constructors. The most commonly used forms are shown here:

      Color(int red, int green, int blue)
      Color(int rgbValue)
      Color(float red, float green, float blue)

The first constructor takes three integers that specify the color as a mix of red, green, and blue. These values must be between 0 and 255, as in this example:

  new Color(255, 100, 100); // light red.

The second color constructor takes a single integer that contains the mix of red, green, and blue packed into an integer. The integer is organized with red in bits 16 to 23, green in bits 8 to 15, and blue in bits 0 to 7. Here is an example of this constructor:

  int newRed = (0xff000000 | (0xc0 << 16) | (0x00 << 8) | 0x00);
  Color darkRed = new Color(newRed);

The final constructor, Color(float, float, float), takes three float values (between 0.0 and 1.0) that specify the relative mix of red, green, and blue. Once you have created a color, you can use it to set the foreground and/or background color by using the setForeground( ) and setBackground( ) methods described. You can also select it as the current drawing color.


Color Methods

The Color class defines several methods that help manipulate colors. They are examined here.

Using Hue, Saturation, and Brightness
The hue-saturation-brightness (HSB) color model is an alternative to red-green-blue (RGB) for specifying particular colors. Figuratively, hue is a wheel of color. The hue is specified with a number between 0.0 and 1.0 (the colors are approximately: red, orange, yellow, green, blue, indigo, and violet). Saturation is another scale ranging from 0.0 to 1.0, representing light pastels to intense hues. Brightness values also range from 0.0 to 1.0, where 1 is bright white and 0 is black. Color supplies two methods that let you convert between RGB and HSB. They are shown here:

      static int HSBtoRGB(float hue, float saturation, float brightness)
      static float[ ] RGBtoHSB(int red, int green, int blue, float values[ ])

HSBtoRGB( ) returns a packed RGB value compatible with the Color(int) constructor. RGBtoHSB( ) returns a float array of HSB values corresponding to RGB integers. If values is not null, then this array is given the HSB values and returned. Otherwise, a new array is created and the HSB values are returned in it.

getRed( ), getGreen( ), getBlue( )
You can obtain the red, green, and blue components of a color independently using getRed( ), getGreen( ), and getBlue( ), shown here:

      int getRed( )
      int getGreen( )
      int getBlue( )

Each of these methods returns the RGB color component found in the invoking Color object in the lower 8 bits of an integer.

getRGB( )
To obtain a packed, RGB representation of a color, use getRGB( ), shown here:

      int getRGB( )

The return value is organized as described earlier.

Setting the Current Graphics Color
By default, graphics objects are drawn in the current foreground color. You can change this color by calling the Graphics method setColor( ):

      void setColor(Color newColor)

Here, newColor specifies the new drawing color. You can obtain the current color by calling getColor( ), shown here:

      Color getColor( )

A Color Demonstration Applet
The following applet constructs several colors and draws various objects using these colors:

  // Demonstrate color.
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="ColorDemo" width=300 height=200>
  </applet>
  */

  public class ColorDemo extends Applet {
    // draw lines
    public void paint(Graphics g) {
      Color c1 = new Color(255, 100, 100);
      Color c2 = new Color(100, 255, 100);
      Color c3 = new Color(100, 100, 255);

      g.setColor(c1);
      g.drawLine(0, 0, 100, 100);
      g.drawLine(0, 100, 100, 0);

      g.setColor(c2);
      g.drawLine(40, 25, 250, 180);
      g.drawLine(75, 90, 400, 400);

      g.setColor(c3);
      g.drawLine(20, 150, 400, 40);
      g.drawLine(5, 290, 80, 19);

      g.setColor(Color.red);
      g.drawOval(10, 10, 50, 50);
      g.fillOval(70, 90, 140, 100);

      g.setColor(Color.blue);
      g.drawOval(190, 10, 90, 30);
      g.drawRect(10, 10, 60, 50);

      g.setColor(Color.cyan);
      g.fillRect(100, 10, 60, 50);
      g.drawRoundRect(190, 10, 60, 50, 15, 15);
    }
  }




Setting the Paint Mode

The paint mode determines how objects are drawn in a window. By default, new output to a window overwrites any preexisting contents. However, it is possible to have new objects XORed onto the window by using setXORMode( ), as follows:

      void setXORMode(Color xorColor)

Here, xorColor specifies the color that will be XORed to the window when an object is drawn. The advantage of XOR mode is that the new object is always guaranteed to be visible no matter what color the object is drawn over. To return to overwrite mode, call setPaintMode( ), shown here:

      void setPaintMode( )

In general, you will want to use overwrite mode for normal output, and XOR mode for special purposes. For example, the following program displays cross hairs that track the mouse pointer. The cross hairs are XORed onto the window and are always visible, no matter what the underlying color is.

  // Demonstrate XOR mode.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;
  /*
    <applet code="XOR" width=400 height=200>
    </applet>
  */

  public class XOR extends Applet {
    int chsX=100, chsY=100;

    public XOR() {
      addMouseMotionListener(new MouseMotionAdapter() {
        public void mouseMoved(MouseEvent me) {
          int x = me.getX();
          int y = me.getY();
          chsX = x-10;
          chsY = y-10;
          repaint();
        }
      });
    }

    public void paint(Graphics g) {
      g.drawLine(0, 0, 100, 100);
      g.drawLine(0, 100, 100, 0);
      g.setColor(Color.blue);
      g.drawLine(40, 25, 250, 180);
      g.drawLine(75, 90, 400, 400);
      g.setColor(Color.green);
      g.drawRect(10, 10, 60, 50);
      g.fillRect(100, 10, 60, 50);
      g.setColor(Color.red);
      g.drawRoundRect(190, 10, 60, 50, 15, 15);
      g.fillRoundRect(70, 90, 140, 100, 30, 40);
      g.setColor(Color.cyan);
      g.drawLine(20, 150, 400, 40);
      g.drawLine(5, 290, 80, 19);

      // xor cross hairs
      g.setXORMode(Color.black);
      g.drawLine(chsX-10, chsY, chsX+10, chsY);
      g.drawLine(chsX, chsY-10, chsX, chsY+10);
      g.setPaintMode();
    }
  }




Working with Fonts

The AWT supports multiple type fonts. Fonts have emerged from the domain of traditional typesetting to become an important part of computer-generated documents and displays. The AWT provides flexibility by abstracting font-manipulation operations and allowing for dynamic selection of fonts.

Beginning with Java 2, fonts have a family name, a logical font name, and a face name. The family name is the general name of the font, such as Courier. The logical name specifies a category of font, such as Monospaced. The face name specifies a specific font, such as Courier Italic. Fonts are encapsulated by the Font class. Several of the methods defined. The Font class defines these variables:

String name:  Name of the font.

float pointSize:  Size of the font in points.

int size:  Size of the font in points.

int style:  Font style.


Some Methods Defined by Font

static Font decode(String str):  Returns a font given its name.

boolean equals(Object FontObj):  Returns true if the invoking object contains the same font as that specified by FontObj. Otherwise, it returns false.

String getFamily( ):  Returns the name of the font family to which the invoking font belongs.

static Font getFont(String property):  Returns the font associated with the system property specified by property. null is returned if property does not exist.

static Font getFont(String property, Font defaultFont):  Returns the font associated with the system property specified by property. The font specified by defaultFont is returned if property does not exist.

String getFontName():  Returns the face name of the invoking font. (Added by Java 2)

String getName( ):  Returns the logical name of the invoking font.

int getSize( ):  Returns the size, in points, of the invoking font.

int getStyle( ):  Returns the style values of the invoking font.

int hashCode( ):  Returns the hash code associated with the invoking object.

boolean isBold( ):  Returns true if the font includes the BOLD style value. Otherwise, false is returned.

boolean isItalic( ):  Returns true if the font includes the ITALIC style value. Otherwise, false is returned.

boolean isPlain( ):  Returns true if the font includes the PLAIN style value. Otherwise, false is returned.

String toString( ):  Returns the string equivalent of the invoking font.


Determining the Available Fonts

When working with fonts, often you need to know which fonts are available on your machine. To obtain this information, you can use the getAvailableFontFamilyNames( ) method defined by the GraphicsEnvironment class. It is shown here:

      String[ ] getAvailableFontFamilyNames( )

This method returns an array of strings that contains the names of the available font families. In addition, the getAllFonts( ) method is defined by the GraphicsEnvironment class. It is shown here:

      Font[ ] getAllFonts( )

This method returns an array of Font objects for all of the available fonts. Since these methods are members of GraphicsEnvironment, you need a GraphicsEnvironment reference to call them. You can obtain this reference by using the getLocalGraphicsEnvironment( ) static method, which is defined by GraphicsEnvironment. It is shown here:

      static GraphicsEnvironment getLocalGraphicsEnvironment( )

Here is an applet that shows how to obtain the names of the available font families:

  // Display Fonts
  /*
  <applet code="ShowFonts" width=550 height=60>
  </applet>
  */
  import java.applet.*;
  import java.awt.*;
  
  public class ShowFonts extends Applet {
    public void paint(Graphics g) {
      String msg = "";
      String FontList[];

      GraphicsEnvironment ge =
        GraphicsEnvironment.getLocalGraphicsEnvironment();
      FontList = ge.getAvailableFontFamilyNames();
      for(int i = 0; i < FontList.length; i++)
        msg += FontList[i] + " ";

      g.drawString(msg, 4, 16);
    }
  }

Sample output from this program is shown next. However, when you run this program, you may see a different list of fonts than the one shown in this illustration.

Prior to Java 2, you would use the method getFontList( ) defined by the Toolkit class to obtain a list of fonts. This method is now deprecated and should not be used by new programs.


Creating and Selecting a Font

To select a new font, you must first construct a Font object that describes that font. One Font constructor has this general form:

      Font(String fontName, int fontStyle, int pointSize)

Here, fontName specifies the name of the desired font. The name can be specified using either the logical or face name. All Java environments will support the following fonts: Dialog, DialogInput, Sans Serif, Serif, Monospaced, and Symbol. Dialog is the font used by your system’s dialog boxes. Dialog is also the default if you don’t explicitly set a font. You can also use any other fonts supported by your particular environment, but be careful—these other fonts may not be universally available.

The style of the font is specified by fontStyle. It may consist of one or more of these three constants: Font.PLAIN, Font.BOLD, and Font.ITALIC. To combine styles, OR them together. For example, Font.BOLD | Font.ITALIC specifies a bold, italics style.

The size, in points, of the font is specified by pointSize. To use a font that you have created, you must select it using setFont( ), which is defined by Component. It has this general form:

      void setFont(Font fontObj)

Here, fontObj is the object that contains the desired font. The following program outputs a sample of each standard font. Each time you click the mouse within its window, a new font is selected and its name is displayed.

  // Show fonts.
  import java.applet.*;
  import java.awt.*;
  import java.awt.event.*;
  /*
    <applet code="SampleFonts" width=200 height=100>
    </applet>
  */

  public class SampleFonts extends Applet {
    int next = 0;
    Font f;
    String msg;
    public void init() {
      f = new Font("Dialog", Font.PLAIN, 12);
      msg = "Dialog";
      setFont(f);
      addMouseListener(new MyMouseAdapter(this));
    }

    public void paint(Graphics g) {
      g.drawString(msg, 4, 20);
    }
  }

  class MyMouseAdapter extends MouseAdapter {
    SampleFonts sampleFonts;
    public MyMouseAdapter(SampleFonts sampleFonts) {
      this.sampleFonts = sampleFonts;
    }
    public void mousePressed(MouseEvent me) {
      // Switch fonts with each mouse click.
      sampleFonts.next++;
      switch(sampleFonts.next) {
      case 0:
        sampleFonts.f = new Font("Dialog", Font.PLAIN, 12);
        sampleFonts.msg = "Dialog";
        break;
      case 1:
        sampleFonts.f = new Font("DialogInput", Font.PLAIN, 12);
        sampleFonts.msg = "DialogInput";
        break;
      case 2:
        sampleFonts.f = new Font("SansSerif", Font.PLAIN, 12);
        sampleFonts.msg = "SansSerif";
        break;
      case 3:
        sampleFonts.f = new Font("Serif", Font.PLAIN, 12);
        sampleFonts.msg = "Serif";
        break;
      case 4:
        sampleFonts.f = new Font("Monospaced", Font.PLAIN, 12);
        sampleFonts.msg = "Monospaced";
        break;
      }
      if(sampleFonts.next == 4) sampleFonts.next = -1;
      sampleFonts.setFont(sampleFonts.f);
      sampleFonts.repaint();
    }
  }


Obtaining Font Information

Suppose you want to obtain information about the currently selected font. To do this, you must first get the current font by calling getFont( ). This method is defined by the Graphics class, as shown here:

Font getFont( )

Once you have obtained the currently selected font, you can retrieve information about it using various methods defined by Font. For example, this applet displays the name, family, size, and style of the currently selected font:

  // Display font info.
  import java.applet.*;
  import java.awt.*;
  /*
  <applet code="FontInfo" width=350 height=60>
  </applet>
  */

  public class FontInfo extends Applet {
    public void paint(Graphics g) {
      Font f = g.getFont();
      String fontName = f.getName();
      String fontFamily = f.getFamily();
      int fontSize = f.getSize();
      int fontStyle = f.getStyle();

      String msg = "Family: " + fontName;
      msg += ", Font: " + fontFamily;
      msg += ", Size: " + fontSize + ", Style: ";
      if((fontStyle & Font.BOLD) == Font.BOLD)
        msg += "Bold ";
      if((fontStyle & Font.ITALIC) == Font.ITALIC)
        msg += "Italic ";
      if((fontStyle & Font.PLAIN) == Font.PLAIN)
        msg += "Plain ";

      g.drawString(msg, 4, 16);
    }
  }

Creating a Windowed Program & Working with Graphics - Java Tutorials

Creating a Windowed Program

Although creating applets is the most common use for Java’s AWT, it is possible to create stand-alone AWT-based applications, too. To do this, simply create an instance of the window or windows you need inside main( ). For example, the following program creates a frame window that responds to mouse clicks and keystrokes:

  // Create an AWT-based application.
  import java.awt.*;
  import java.awt.event.*;
  import java.applet.*;

  // Create a frame window.
  public class AppWindow extends Frame {
    String keymsg = "This is a test.";
    String mousemsg = "";
    int mouseX=30, mouseY=30;

    public AppWindow() {
      addKeyListener(new MyKeyAdapter(this));
      addMouseListener(new MyMouseAdapter(this));
      addWindowListener(new MyWindowAdapter());
    }

    public void paint(Graphics g) {
      g.drawString(keymsg, 10, 40);
      g.drawString(mousemsg, mouseX, mouseY);
    }

    // Create the window.
    public static void main(String args[]) {
      AppWindow appwin = new AppWindow();

      appwin.setSize(new Dimension(300, 200));
      appwin.setTitle("An AWT-Based Application");
      appwin.setVisible(true);
    }
  }

  class MyKeyAdapter extends KeyAdapter {
    AppWindow appWindow;
    public MyKeyAdapter(AppWindow appWindow) {
      this.appWindow = appWindow;
    }
    public void keyTyped(KeyEvent ke) {
      appWindow.keymsg += ke.getKeyChar();
      appWindow.repaint();
    };
  }

  class MyMouseAdapter extends MouseAdapter {
    AppWindow appWindow;
    public MyMouseAdapter(AppWindow appWindow) {
      this.appWindow = appWindow;
    }
    public void mousePressed(MouseEvent me) {
      appWindow.mouseX = me.getX();
      appWindow.mouseY = me.getY();
      appWindow.mousemsg = "Mouse Down at " + appWindow.mouseX +
                           ", " + appWindow.mouseY;
      appWindow.repaint();
    }
  }

  class MyWindowAdapter extends WindowAdapter {
    public void windowClosing(WindowEvent we) {
      System.exit(0);
    }
  }

Once created, a frame window takes on a life of its own. Notice that main( ) ends with the call to appwin.setVisible(true). However, the program keeps running until you close the window. In essence, when creating a windowed application, you will use main( ) to launch its top-level window. After that, your program will function as a GUI-based application, not like the console-based programs used earlier.


Displaying Information Within a Window

In the most general sense, a window is a container for information. Although we have already output small amounts of text to a window in the preceding examples, we have not begun to take advantage of a window’s ability to present high-quality text and graphics. Indeed, much of the power of the AWT comes from its support for these items. For this reason, the remainder of this chapter discusses Java’s text-, graphics-, and font-handling capabilities. As you will see, they are both powerful and flexible.




Working with Graphics

The AWT supports a rich assortment of graphics methods. All graphics are drawn
relative to a window. This can be the main window of an applet, a child window of
an applet, or a stand-alone application window. The origin of each window is at the
top-left corner and is 0,0. Coordinates are specified in pixels. All output to a window
takes place through a graphics context. A graphics context is encapsulated by the
Graphics class and is obtained in two ways:
  • It is passed to an applet when one of its various methods, such as paint( ) or update( ), is called.
  • It is returned by the getGraphics( ) method of Component.

For the remainder of the examples in this chapter, we will be demonstrating graphics in the main applet window. However, the same techniques will apply to any other window.

The Graphics class defines a number of drawing functions. Each shape can be drawn edge-only or filled. Objects are drawn and filled in the currently selected graphics color, which is black by default. When a graphics object is drawn that exceeds the dimensions of the window, output is automatically clipped. Let’s take a look at several of the drawing methods.


Drawing Lines

Lines are drawn by means of the drawLine( ) method, shown here:

      void drawLine(int startX, int startY, int endX, int endY)

drawLine( ) displays a line in the current drawing color that begins at startX,startY and ends at endX,endY.

The following applet draws several lines:

  // Draw lines
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="Lines" width=300 height=200>
  </applet>
  */
  public class Lines extends Applet {
    public void paint(Graphics g) {
      g.drawLine(0, 0, 100, 100);
      g.drawLine(0, 100, 100, 0);
      g.drawLine(40, 25, 250, 180);
      g.drawLine(75, 90, 400, 400);
      g.drawLine(20, 150, 400, 40);
      g.drawLine(5, 290, 80, 19);
    }
  }


Drawing Rectangles

The drawRect( ) and fillRect( ) methods display an outlined and filled rectangle, respectively. They are shown here:

      void drawRect(int top, int left, int width, int height)
      void fillRect(int top, int left, int width, int height)

The upper-left corner of the rectangle is at top,left. The dimensions of the rectangle are specified by width and height. To draw a rounded rectangle, use drawRoundRect( ) or fillRoundRect( ), both shown here:

      void drawRoundRect(int top, int left, int width, int height,
                                          int xDiam, int yDiam)

      void fillRoundRect(int top, int left, int width, int height,
                                      int xDiam, int yDiam)

A rounded rectangle has rounded corners. The upper-left corner of the rectangle is at top,left. The dimensions of the rectangle are specified by width and height. The diameter of the rounding arc along the X axis is specified by xDiam. The diameter of the rounding arc along the Y axis is specified by yDiam.

The following applet draws several rectangles:

  // Draw rectangles
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="Rectangles" width=300 height=200>
  </applet>
  */
  
  public class Rectangles extends Applet {
    public void paint(Graphics g) {
      g.drawRect(10, 10, 60, 50);
      g.fillRect(100, 10, 60, 50);
      g.drawRoundRect(190, 10, 60, 50, 15, 15);
      g.fillRoundRect(70, 90, 140, 100, 30, 40);
    }
  }


Drawing Ellipses and Circles

To draw an ellipse, use drawOval( ). To fill an ellipse, use fillOval( ). These methods are shown here:

      void drawOval(int top, int left, int width, int height)
      void fillOval(int top, int left, int width, int height)

The ellipse is drawn within a bounding rectangle whose upper-left corner is specified by top,left and whose width and height are specified by width and height. To draw a circle, specify a square as the bounding rectangle.

The following program draws several ellipses:

  // Draw Ellipses
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="Ellipses" width=300 height=200>
  </applet>
  */
  
  public class Ellipses extends Applet {
    public void paint(Graphics g) {
      g.drawOval(10, 10, 50, 50);
      g.fillOval(100, 10, 75, 50);
      g.drawOval(190, 10, 90, 30);
      g.fillOval(70, 90, 140, 100);
    }
  }


Drawing Arcs

Arcs can be drawn with drawArc( ) and fillArc( ), shown here:

      void drawArc(int top, int left, int width, int height, int startAngle,
                              int sweepAngle)

      void fillArc(int top, int left, int width, int height, int startAngle,
                          int sweepAngle)
                         
The arc is bounded by the rectangle whose upper-left corner is specified by top,left and whose width and height are specified by width and height. The arc is drawn from startAngle through the angular distance specified by sweepAngle. Angles are specified in degrees. Zero degrees is on the horizontal, at the three o’clock position. The arc is drawn counterclockwise if sweepAngle is positive, and clockwise if sweepAngle is negative. Therefore, to draw an arc from twelve o’clock to six o’clock, the start angle would be 90 and the sweep angle 180.

The following applet draws several arcs:

  // Draw Arcs
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="Arcs" width=300 height=200>
  </applet>
  */

  public class Arcs extends Applet {
    public void paint(Graphics g) {
      g.drawArc(10, 40, 70, 70, 0, 75);
      g.fillArc(100, 40, 70, 70, 0, 75);
      g.drawArc(10, 100, 70, 80, 0, 175);
      g.fillArc(100, 100, 70, 90, 0, 270);
      g.drawArc(200, 80, 80, 80, 0, 180);
    }
  }


Drawing Polygons

It is possible to draw arbitrarily shaped figures using drawPolygon( ) and fillPolygon( ), shown here:

      void drawPolygon(int x[ ], int y[ ], int numPoints)
      void fillPolygon(int x[ ], int y[ ], int numPoints)

The polygon’s endpoints are specified by the coordinate pairs contained within the x and y arrays. The number of points defined by x and y is specified by numPoints. There are alternative forms of these methods in which the polygon is specified by a Polygon object. 

The following applet draws an hourglass shape:

  // Draw Polygon
  import java.awt.*;
  import java.applet.*;
  /*
  <applet code="HourGlass" width=230 height=210>
  </applet>
  */

  public class HourGlass extends Applet {
    public void paint(Graphics g) {
      int xpoints[] = {30, 200, 30, 200, 30};
      int ypoints[] = {30, 30, 200, 200, 30};
      int num = 5;

      g.drawPolygon(xpoints, ypoints, num);
    }
  }


Sizing Graphics

Often, you will want to size a graphics object to fit the current size of the window in which it is drawn. To do so, first obtain the current dimensions of the window by calling getSize( ) on the window object. It returns the dimensions of the window encapsulated within a Dimension object. Once you have the current size of the window, you can scale your graphical output accordingly.

To demonstrate this technique, here is an applet that will start as a 200×200-pixel square and grow by 25 pixels in width and height with each mouse click until the applet gets larger than 500×500. At that point, the next click will return it to 200×200, and the process starts over. Within the window, a rectangle is drawn around the inner border of the window; within that rectangle, an X is drawn so that it fills the window. This applet works in appletviewer, but it may not work in a browser window.

  // Resizing output to fit the current size of a window.
  import java.applet.*;
  import java.awt.*;
  import java.awt.event.*;
  /*
    <applet code="ResizeMe" width=200 height=200>
    </applet>
  */

  public class ResizeMe extends Applet {
    final int inc = 25;
    int max = 500;
    int min = 200;
    Dimension d;

    public ResizeMe() {
      addMouseListener(new MouseAdapter() {
        public void mouseReleased(MouseEvent me) {
          int w = (d.width + inc) > max?min :(d.width + inc);
          int h = (d.height + inc) > max?min :(d.height + inc);
          setSize(new Dimension(w, h));
        }
      });
    }
    public void paint(Graphics g) {
      d = getSize();

      g.drawLine(0, 0, d.width-1, d.height-1);
      g.drawLine(0, d.height-1, d.width-1, 0);
      g.drawRect(0, 0, d.width-1, d.height-1);
    }
  }