1. 程式人生 > >JAVA圖形程式設計入門(連載2)

JAVA圖形程式設計入門(連載2)

JAVA圖形程式設計入門

,

TIP450--TIP477 

450 Drawing3-D Rectangles

450 畫3-D矩形

Almost all graphical user interfaces designed today have athree-dimensional look. Command buttons appear to rise off the page, and whenyou click on a button, the button appears to push in. You can create this 3-Dlook by using a simple highlight and shadow. Assuming that light comes from thetop-left, by applying highlight on the top and left side together with shadowon the right and bottom side, you can create a raised

look. Similarly, by placing a shadow on the top and left sidetogether with highlight on the right and bottom side, you can create apushed-in look. Figure 450 shows a raised and a pushed-in rectangle.

幾乎所有現在設計的圖形使用者介面都有三維的式樣. 命令按鈕顯得從頁面上凸出來,而當你點選到某個按鈕時,這個按鈕看上去就被按下去了. 你可以利用簡單的增亮色彩和新增陰影的方法來建立這種3-D的式樣. 設想光線來自左上方,則在圖形的左上方加亮,而同時要在其右下方新增陰影,這一圖形就是凸的樣子了. 類似地,如果在圖形的左上方加陰影,而同時要在其右下方加亮色,這一圖形就有凹下去的樣子. 圖450顯示了一個凸出的和一個凹下去的長方形.

Production: Insert figurefig127.bmp  [MCC]


Figure 450Raised and pushed-in rectangle using highlights and shadows.

圖450 利用增亮和陰影產生凸起和凹下的矩形

The Java AWT provides the draw3DRect with which you can draw a3-D rectangle:

Java AWT提供了draw3DRect功能,利用它你可以來畫一個3-D矩形:

draw3DRect(int x, inty, int width, int height, boolean raised);

The draw3DRect method is very similar to the drawRect method,but includes the extra raised parameter. You create a raised rectangle byspecifying true or a pushed-in rectangle by specifying false.

Draw3DRect方法與drawRect方法是很相象的,但多了一個額外的凸起引數. 你只要指明此引數為true就可畫一個凸出的3-D矩形, 而指明此引數為false時就可畫一個凹進的3-D矩形.

451 Drawinga Filled 3D Rectangle

451 畫一填色的3-D矩形

In Tip 450, you learned that you can draw a 3-D rectangle usingthe draw3DRect method. Depending on your programs design, there may be timeswhen you will want a filled 3-D rectangle. To display a filled 3-D rectangle,your programs can use the fill3DRect method, the format of which is as follows:

在 TIP 450 中, 你已知道了你可以用draw3DRect來畫一個3-D矩形.根據你的程式的情況,有時你會需要畫一個3-D的填色矩形. 為了畫一個填色3-D矩形,  你的程式可以使用fill3DRect方法. fill3DRect方法的格式如下:

fill3DRect(int x, inty, int width, int height,

  boolean raised);

The fill3DRect method uses the same set of parameters as thedraw3DRect method. To create a raised rectangle, use the value true for theraised parameter. Likewise, to display a pushed-in rectangle, use the valuefalse.

Fill3DRect方法與draw3DRect使用相同的引數. 為了建立一個凸起的矩形,raised引數為true. 同樣,為了建立一個凹進的矩形,raised引數應為false.

452Implementing Your Own 3-D Rectangle

452 實現你自己的3-D矩形

In Tip 450 and Tip 451, you learned how to draw 3-D rectanglesusing the draw3DRect and fill3DRect methods. If you use these methods withinyour program, you may find the 3-D effect very hard to see. The problem withthe built-in methods is that Java only draws the highlight and shadow borders onepixel wide. The following applet, three_d_rect.java, implements betterdraw3DRect and fill3DRect methods with borders that are three pixels wide, asshown in Figure 452:

在 TIP 450 和 TIP 451 中, 你已知道了怎樣利用draw3DRect 和 fill3DRect 方法去畫一個3-D矩形. 如果你在程式中使用了這些方法, 你可以發現3-D的效果不容易看清. 這種內建方法的問題在於, Java只用一個象素的線寬來畫增亮的及陰影的邊框線.以下的應用程式 three_d_rect.java利用draw3DRect 和 fill3DRect方法產生了有較好3-D效果的圖形,如圖452所示的,它帶有三個象素寬度的邊框:  

import java.applet.*;

import java.awt.*;

public classthree_d_rect extends Applet {

   public void draw3DRect(Graphics g, int x,int y,

      int width, int height, boolean raised)

     {

       g.draw3DRect(x, y, width-1, height-1,raised);

       g.draw3DRect(x+1, y+1, width-3,height-3, raised);

       g.draw3DRect(x+2, y+2, width-, height-,raised);

     }

   public void fill3DRect(Graphics g, int x,int y,

      int width, int height, boolean raised)

     {

       g.draw3DRect(x, y, width-1, height-1,raised);

      g.draw3DRect(x+1, y+1, width-3, height-3, raised);

       g.draw3DRect(x+2, y+2, width-, height-,raised);

       g.fillRect(x+3, y+3, width-6, height-6);

     }

   public void paint(Graphics g)

     {

       g.setColor(Color.gray);

       draw3DRect(g, 10, , 80, , true);

       draw3DRect(g, 130, , 80, , false);

       fill3DRect(g, 10, , 80, , true);

       fill3DRect(g, 130, , 80, , false);

     }

 }

 

Figure 452 Drawing 3-D rectangles.

圖452 畫3-D;矩形

453 Usingthe darker and brighter Methods

453 使用darker和 brighter 方法

In Tip 452, you learned that you can create a 3-D effect usinghighlights and shadows. The Color class darker and brighter methods can helpyou obtain the highlight and shadow colors. You can also use these methods tocreate special effects like the one shown Figure 453, which was created by thebright_dark.java applet, as shown:

在 TIP 452 中, 你已知道了可以用加亮和陰影來建立3-D效果. Color類的darker和brighter方法能幫你得到其它的變亮和變暗色彩. 你同樣可以利用這些方法來建立類似於圖453所示的特殊效果, 它們是由應用程式bright_dark.java產生的:

import java.applet.*;

import java.awt.*;

public classbright_dark extends Applet {

   Color dark_red = new Color(, 0, 0);

   Color light_gray = new Color(2, 2, 2);

   public void paint(Graphics g)

     {

       Color color;

       // brighter colors

       color = dark_red;

       for (int i = 0; i < 16; i++)

         {

           g.setColor(color);

           g.fillRect(0, i*, 300, );

           color = color.brighter();

         }

       // darker colors

       color = light_gray;

       for(int i = 16; i < 32; i++)

         {

           g.setColor(color);

           g.fillRect(0, i*, 300, );

           color = color.darker();

         }

     }

 }

 

Figure 453 Gradient color effectsusing the Color class bright and dark methods.

圖453 利用Color類的brighter和darker方法產生漸變的色彩效應

454 FindingRegions That Need Updating Using the getClipRect Method

454 尋找需要利用getClipRect方法重新整理的區域

When an area of a Java program needs to be redrawn, Java willautomatically call the update and paint methods. If only a portion of thedrawing area needs updating, Java will try to find the smallest rectangle thatencloses the required area and set it as the Graphics objects clipping region.Java then passes the Graphics object to the update and paint methods. Theupdate and paint methods ignore all drawings outside of the clipping rectangle,which allows faster screen updates.

當Java程式的一個區域需要重畫時,Java就自動呼叫update 和 paint 方法. 如果作圖區域中只有一部分需要重新整理, Java將尋找出包含所需區域的最小矩形,並將其設成為一個Graphics物件的剪下區(clipping region). 然後Java把這Graphics物件傳給update和paint方法. update和paint方法將不考慮剪下區之外的所有作圖,這樣使螢幕的重新整理變快.

In most Java programs, programmers override the paint or updatemethod to draw the entire applet. To improve your programs performance, you candetermine the clipping region that needs updating and then only redraw thatportion of the window. To determine the clipping area, your programs can callthe getClipRect method. The following applet, get_cliprect.java, displays theclipping area that needs updating. Experiment with this applet by hiding andexposing part of the applet window with another application.

在Java程式中, 有的程式設計師不利用paint 或 update方法,而把整個應用程式區域重畫一遍. 為了改進你的程式的效能, 你可以定出需要重新整理的剪下區, 然後只重畫位於剪下區視窗內的那一部分. 為了確定剪下區的範圍, 你的程式可以呼叫getClipRect方法. 以下的程式get_ClipRect.java顯示了需要重新整理的剪下區. 本程式中利用隱蔽和暴露部分視窗的經驗在編寫其它應用程式時也是有用的.

import java.applet.*;

import java.awt.*;

public classget_cliprect extends Applet {

   public void paint(Graphics g)

     {

       // draw a X on the screen

       g.drawLine(0, 0, 300, 100);

       g.drawLine(300, 0, 0, 100);

       // print clipping rectangle to standardout

       System.out.println("ClippingRect:" + g.getClipRect());

     }

}

455Creating a Rectangle

455 建立一個矩形物件

As you learned in Tip 454, the getClipRect method returns aRectangle object that defines the current clipping region. Depending on yourapplets purpose, you may need to create your own Rectangle object. For example,you may want to define a clickable region within which the user can click themouse to select different objects. To create a Rectangle object, use one of thefollowing Rectangle constructors:

正如你在TIP 454 中所瞭解的那樣, getClipRect方法返回一個矩形物件,它確定了當前的剪下區的大小. 按照你的應用程式的用途, 你有時會需要建立你自己的矩形物件.例如, 你可能需要定義一個可點選的(clickable)區, 使用者利用mouse點選到區域中, 來選擇不同的物件. 為了建立一個Rectangle物件,可使用以下各種Rectangle建構函式:

Rectangle();

Rectangle(int x, inty, int width, int height);

Rectangle(int width,int height);

Rectangle(Point p,Dimension d);

Rectangle(Point);

Rectangle(Dimension);

These constructors create the Rectangle object and initializethe x, y, width, and height fields which define the rectangles size andlocation.

這些建構函式建立了Rectangle物件, 並初始化x, y, width, 和height域, 來規定Rectangle物件的大小和位置.

456Understanding the Point and Dimension Class

456 瞭解Point類和Dimension類

Within an applet that performs graphics operations,there will be many times when you need to store x and y coordinates. In suchcases, your programs can use the Point class to create an object to store apoints coordinates. To create a Point object, use the following constructor:

在一執行圖形操作的應用程式中, 你常常會需要儲存x,y座標. 這時,你的程式可以利用Point類來建立一個存放點的座標的物件. 為了建立一個Point物件,可使用以下建構函式:

Point(int x, int y);

In a similar way, there will be times when your programs need tostore information about a graphic objects width and height. To store suchinformation, your programs can create a Dimension object using one of thefollowing constructor methods:

同樣的理由, 你的應用程式有時可能需要儲存圖形物件的寬度和高度. 為了儲存圖形物件的這些資訊, 你的程式可以利用以下建構函式之一來建立一個Dimension物件:

Dimension();

Dimension(Dimensiond);

Dimension(int width,int height);

The first constructor, with no argument, creates a Dimensionobject of zero width and zero height. The second constructor, with a Dimensionargument, creates a copy of the specified dimension. The third constructorcreates a Dimension object with the specified width and height.

不帶自變數的第一個建構函式建立了一個零寬度零高度的Dimension物件. 帶一個自變數的第二個建構函式建立了一個指定維數(dimension)的拷貝. 第三個建構函式建立了一個帶由指定寬度和指定高度的Dimension物件.

457Checking If a Point Is Inside a Rectangle

457 檢測一個點是否在一個矩形的內部

Within a graphics-based program, you may need to determine if apoint (x and y coordinates) reside within a rectangles coordinates. Todetermine if a point is within a rectangle, your programs can use the Rectangleclass inside method. The following applet, click_rect.java, implements twoclickable rectangular regions using a Rectangle object. When the user clickshis or her mouse within a region, the applet will display a message so stating:

在一基於圖形的程式中,你可能需要確定一個點是否位於一個矩形內. 為了確定一個點是否位於一個矩形內,你的程式可以使用Rectangle類的inside方法. 以下的應用程式click_rect.java 利用Rectangle物件建立了兩個可點選的矩形區域. 當用戶在區域內點選他或她的mouse時,應用程式就會顯示一個說明這一情況的資訊:

import java.applet.*;

import java.awt.*;

public class click_rect extends Applet {

   Rectangle a_rect = new Rectangle(10,  10, 80, );

   Rectangle b_rect = new Rectangle(100, 10,80, );

   public boolean mouseDown(Event e, int x, inty)

     {

       if (a_rect.inside(x,y))         // rectangle A clicked

         System.out.println("Aclicked.");

       if (b_rect.inside(x,y))         // rectangle B clicked

         System.out.println("Bclicked.");

       return true;

     }

   public void paint(Graphics g)

     {

        // draw the 2 clickable rectangles

        g.setColor(Color.yellow);

        g.fillRect(a_rect.x, a_rect.y,a_rect.width, a_rect.height);

        g.fillRect(b_rect.x, b_rect.y,b_rect.width, b_rect.height);

        g.setColor(Color.black);

        g.drawString("A", a_rect.x +a_rect.width/2,

                     a_rect.y +a_rect.height/2);

        g.drawString("B", b_rect.x +b_rect.width/2,

                     b_rect.y +b_rect.height/2);

     }

 }

Figure 457 shows a screen shot from the click_rect.java applet.As you can see, the applet defines two clickable rectangular regions: A and B.When the applet detects a mouse click, the applet will check if the clicklocation is inside one of these two rectangles. If the click location is insideA or B, the applet will display a message to the console window.

圖457 顯示了一個由應用程式click_rect.java產生的螢幕. 你可以看出,應用程式定義了兩個可點選的矩形區:A 和 B. 當應用程式檢查mouse點選,它將檢查點選的位置是否在其中一個區域之內. 如果點選的位置是在區域A或B之內,應用程式將在使用者的顯示器視窗上顯示一個資訊.

Figure 457 An Applet with twoclickable rectangles.

圖457 產生兩個可點選矩形的應用程式

458Checking If Two Rectangles Intersect

458 檢測兩矩形是否相交

Within a graphics-based program, there may be times when youneed to test if two rectangle objects intersect. To determine if two Rectangleobjects intersect, your programs can use the Rectangle class intersects method.A game program, for example, might use the intersects method to detect if amissile has hit a spaceship. The following applet, intersects.java, illustratesthe use of the intersects method. Take time to experiment with the rectanglecoordinates, and test whether the rectangles intersect.

在一圖形軟體中,有時你會需要測試一下兩個矩形是否相交. 為了測試兩個矩形是否相交,你的應用程式可以使用Rectangle類intersects方法. 例如,一個game程式可能要用 intersects方法來檢查一個火箭是否擊中了宇宙飛船. 以下的應用程式intersects.java, 說明了intersects方法的用法. 化時間試驗一下這些矩形座標,看它們是否相交.

import java.applet.*;

import java.awt.*;

public classintersects extends Applet {

   Rectangle g_rect = new Rectangle(10,  10, 80, );

   Rectangle y_rect = new Rectangle(20, 20, 80,);

   public void paint(Graphics g)

     {

        // draw the rectangles

        g.setColor(Color.yellow);

        g.drawRect(y_rect.x, y_rect.y,y_rect.width, y_rect.height);

        g.setColor(Color.green);

        g.drawRect(g_rect.x, g_rect.y,g_rect.width, g_rect.height);

        g.setColor(Color.black);

        if (y_rect.intersects(g_rect))

          g.drawString("The two rectanglesintersect.", 10,90);

    }

 }

459 Usingthe intersection and union Methods

459 使用intersection方法(求交法) 和 union方法(求和法)

When your program uses Rectangle objects, you may need todetermine the screen region that holds both objects, or if two Rectangle objectsintersect. To find the intersection or the union of two rectangles, you can usethe Rectangle class intersection and union method. The intersection methodreturns the area where two Rectangle objects overlap. That is, the intersectionmethod returns the area that two Rectangle objects have in common.

當你的程式使用Rectangle 物件時, 你可能需要確定同時包含著兩個物件的區域(區域的和),或者被兩個物件同時包含的區域(區域的交). 為了確定區域的交與和,你可以使用Rectangle類的 intersection方法和 union方法.  Intersection方法返回的是兩個物件重疊的區域, 也就是兩個物件的共同區域.

The union method, on the other hand, behaves differently thanyou might expect. The union method returns the smallest rectangle that enclosestwo Rectangle objects, instead of returning just the area covered by bothobjects. Figure 459 illustrates the behavior of the intersection and unionmethods.

另一方面, union方法產生區域可能和你期望的不同, 它返回的是包含著兩個物件的一個最小矩型區域, 而不是正好這兩個區域所覆蓋的區域. 圖459說明了intersection方法與 union 方法的效果.

Figure 459 The intersection and unionof two rectangles.

圖459 兩個區域的交與"和"

460Creating a Polygon

460 建立一個多邊形

To define complex shapes like triangles and pentagons,your programs can use a Polygon object. To create a Polygon object, use one ofthe following constructor methods:

要建立三角形,五邊形這樣的複雜形狀,你的程式可一使用Polygon 物件. 為了建立一個Polygon物件,你可使用以下的建構函式:

Polygon();

Polygon(int xpoints[],int ypoints[], int npoints);

If you use the Polygon constructor without arguments, you willneed to use the addPoint method to define the polygons points. The followingapplet, poly_object.java, creates two polygons using each constructor. Figure460 illustrates how the Graphics class fillPolygon method displays polygons.

如果你使用了帶由引數的 Polygon建構函式, 你將需要用addPoint方法來定義多邊形的頂點. 以下的應用程式,poly_object.java,利用建構函式建立了兩個多邊形.圖460說明了怎樣利用 Graphics 類的 fillPolygon 方法來縣示多邊形.

Production: Insert code form  poly_object.java [MCC] - cannot find! phil

Figure 460 An Applet with 3 polygons.

圖460 生成3個多邊形的小應用程式

Rickhave anthony fax you the code forpoly_object.java.

461Checking if a Point is Inside a Polygon

461 檢測一點是否在一多邊形內

In Tip 460, you learned how to check if a specific point resideswithin a Rectangle object. In a similar way, there may be times when you needto know if a point resides within a Polygon object. For example, depending onthe shapes that appear within the applet window, you may want to create aclickable region that is defined by a polygon. The following applet,click_poly.java, creates three clickable triangles of different colors.

在TIP 460 中你已知道了怎樣檢測一點是否位於一個矩形的內部. 同樣,有時你會需要檢測一點是否位於一個多邊形的內部. 例如, 根據應用程式視窗內的一個物體形狀,你可能要建一個由多邊形定義的可點選的區域. 以下應用程式click_poly.java, 建立了三個可點選的不同色彩的三角形.

import java.applet.*;

import java.awt.*;

public classclick_poly extends Applet {

   int a_xpoints[] = { , 10, 70 };

   int a_ypoints[] = { 20, ,  };

   int a_len = a_xpoints.length;

   int b_xpoints[] = { 120, 90, 1 };

   int b_ypoints[] = { 20, ,  };

   int b_len = b_xpoints.length;

   Polygon a_poly = new Polygon(a_xpoints,a_ypoints, a_len);

   Polygon b_poly = new Polygon(b_xpoints,b_ypoints, b_len);

   public boolean mouseDown(Event e, int x, inty)

     {

       if (a_poly.inside(x,y))      // Polygon A clicked

         System.out.println("Aclicked.");

       if (b_poly.inside(x,y))       // Polygon B clicked

         System.out.println("Bclicked.");

       return true;

     }

   public void paint(Graphics g)

     {

       // draw the 2 clickable polygons

       g.setColor(Color.yellow);

       g.fillPolygon(a_poly);

       g.setColor(Color.red);

       g.fillPolygon(b_poly);

       g.setColor(Color.black);

       g.drawString("A", 30, );

       g.drawString("B" , 110, );

    }

 }

462 Findingthe Bounding Box of a Polygon

462 尋找多邊形的包圍矩形

In some drawing programs, such as CorelDRAW, when you select anobject, the program creates a box to enclose the object which has handles thatlet you resize or move the object. In Java, a bounding box is the smallest boxthat contains a given polygon. The Polygon class getBoundingBox method returnsthe bounding box for a Polygon object. The following applet, boundbox.java,draws a Polygon object and then uses the getBoundingBox method to draw abounding box. In addition, the program uses the draw_handle method to addediting handles.

在某些圖形軟體中,如CorelDRAW, 當你選擇一個物件時, 程式將建立一個包圍這一物件的方框(box), 使你可以改變它的大小或移動位置. 在Java中,包圍框是包含已給多邊形的最小的框. Polygon類中的getBoundingBox 方法返回了多邊形的最小包圍框. 以下的程式,boundbox.java, 畫出了一個多邊形物件, 然後利用getBoundingBox 方法來畫出一個包圍框.  此外,程式還利用draw_handle 方法進行了編輯處理.

import java.applet.*;

import java.awt.*;

public class boundboxextends Applet {

   int xpoints[] = {30, 90,1, 80, 90, 60};

   int ypoints[] = {30, 10, , 70, , 30};

   int num_pts = ypoints.length;

   Polygon poly = new Polygon(xpoints, ypoints,num_pts);

   void draw_handle(Graphics g, int x, int y)

     {

       g.fillRect(x-3, y-3, 7, 7);

     }

   public void paint(Graphics g)

     {

       // draw the polygons

       g.setColor(Color.red);

       g.fillPolygon(poly);

       Rectangle bbox = poly.getBoundingBox();

       g.setColor(Color.black);

       g.drawRect(bbox.x, bbox.y, bbox.width,bbox.height);

       draw_handle(g, bbox.x, bbox.y);

       draw_handle(g, bbox.x + bbox.width,bbox.y);

       draw_handle(g, bbox.x, bbox.y +bbox.height);

       draw_handle(g, bbox.x + bbox.width,bbox.y + bbox.height);

     }

 }

Figure 462 shows the output of the boundbox.java applet.Although this program does not allow any actual editing, you can use theprogram as the basis of your own drawing program.

圖462 顯示了應用程式boundbox.java 的輸出. 這個程式雖然不允許作任何實際的編輯, 但你可把此程式作為你的畫圖程式的一個基礎.

Figure 462 An applet illustrating the getBoundingBoxmethod.

圖462 說明getBoundingBox方法如何使用的一個小應用程式

463Creating Fonts

463 建立字型

In previous tips, you have learned how to draw text to thescreen. In each case, the program drew the text using the default font. Withinyour programs, you can change the current font by creating new Font objects ofdifferent names, styles, and point sizes using the Font constructor, the formatof which is as follows:

在以上的TIP中,你已知道了怎樣在螢幕上畫字. 程式畫字時每次都使用預設字型. 在你的程式中, 你可以利用Font建構函式來建立不同名稱,不同型式(style),不同大小的字型物件, 由次來改變當前的預設字型.Font建構函式的格式如下:

Font(String name, intstyle, int size);

The name parameter specifies the font name, such as Courier orTimesRoman; Tip 464 will show you how to get a list of available fonts. Thesecond parameter specifies the font style, which can be Font.PLAIN, Font.BOLD,Font.ITALIC, or the combination of BOLD and ITALIC, such as Font.BOLD +Font.ITALIC. The third parameter specifies the fonts point size. For example,the following method call creates a 1 point bold

Courier font:

Font函式中指示的name引數可以是 Couriar, Times, Roman等字型名; TIP 464 將向你顯示怎樣獲得一系列的可用字型. 第二個引數style指明瞭字型的型式,它可以是Font.PLAIN(普通字型),Font.BOLD(粗體), Font.ITALIC(斜體),或者可以是它們的組合, 如Font.BOLD + Font.ITALIC(粗斜體). 第二個引數size指明瞭字型的大小,用點數表示. 例如, 以下方法建立了一個1點couriar粗體:

Font myFont = new Font(Courier,Font.BOLD, 1);

464 FontsAvailable in Java

464 Java中可用的字型

Java defines five platform-independent font names which youshould find available on all platforms. You may use these names as the firstparameter to the Font constructor: Courier, Dialog, Helvetica, TimesRoman, andSymbol. When an applet creates a Font object, Java maps the font to aplatform-dependent font. For example, Java maps the Helvetica font to the Arialfont under Microsoft Windows. You may choose to specify a font name other thanthe five standard ones. However, if the font you specify is not available, Javawill automatically pick an available one for you.

Java定義了五種與平臺無關的字型名, 你在任何平臺都可以使用它們, 你可用它們作為建構函式font的第一個引數,它們是: Courier, Dialog, Helvetica, TimesRoman及 Symbol. 當你的應用程式建立一個 Font 物件時, Java 把字型map到平臺無關的字型. 例如, Java在MicrosoftWindowsay中,將Helvetica體 map到Arial體. 你可以選擇以上五種字型以外的字型, 但, 如果你所指定的字型不能使用,Java將自動為你選用另一種字型.

464 Drawingwith Different Fonts

464 用不同的字型來寫字

In Tip 463, you learned how to create a Font object. To use aFont object to display text, you must use the Graphics class setFont method toselect the font. The following applet, fonts.java, draws several lines of textusing different font names, styles, and point sizes, as shown in Figure 464.

在TIP 463中,你已知道了怎樣建立一字型物件.  為了用一種字型來顯示文字, 你必須用Graphics類的setFont 方法來選擇字型. 以下的fonts.java程式利用不同的字型名,字型型別,以及字型大小來寫了幾行字,如圖464所示那樣:

import java.applet.*;

import java.awt.*;

public class fontsextends Applet {

   Font f1 = new Font("Helvetica",Font.PLAIN, 18);

   Font f2 = new Font("Helvetica",Font.BOLD, 10);

   Font f3 = new Font("Helvetica",Font.ITALIC, 12);

   Font f = new Font("Courier",   Font.PLAIN, 12);

   Font f = new Font("TimesRoman",Font.BOLD + Font.ITALIC, 1);

   Font f6 = new Font("Dialog",Font.ITALIC, 1);

   public void paint(Graphics g)

     {

       g.setFont(f1);

       g.drawString("18pt plainHelvetica", , 20);

       g.setFont(f2);

       g.drawString("10pt boldHelvetica", , );

       g.setFont(f3);

       g.drawString("12pt italicHelvetica", , );

       g.setFont(f);

       g.drawString("12pt plainCourier", , 7);

       g.setFont(f);

       g.drawString("1pt bold & italicTimes Roman", , 92);

       g.setFont(f6);

       g.drawString("1pt italicDialog", , 111);

    }

 }

Figure 465 An Applet illustrating theuse of various font names, style, and point sizes.

圖465 一個用來說命各種字型名,字型型別及字型大小用法的小應用程式

466 Gettinga List of Available Fonts

466 獲得一張可用字體表

As you have learned, to display text using a specific font, yourapplets must create a Font object, and then use the setFont method to selectthe font. Before your applet selects a font, you may want to determine if thefont is available. To get a list of available fonts, your programs can use theToolkit class getFontList method. The following applet, font_list.java,illustrates the use of the getFontList method:

正如你所瞭解的那樣,為了用一種特殊的字型來顯示文字,你的應用程式必須先建立字型物件,然後用setFont方法來選擇字型. 在你的應用程式選擇一種字型之前, 你可能想要確定它是否可用的. 為了獲得一張可用字體表, 你的程式可以使用Toolkit類的getFontList方法. 以下的font_list.java程式說明了如何使用getFontList方法:

import java.applet.*;

import java.awt.*;

public class font_listextends Applet {

   public void paint(Graphics g)

     {

       String fontlist[] =getToolkit().getFontList();

       for(int i = 0; i < fontlist.length;i++)

         {

           Font f = new Font(fontlist[i],Font.BOLD, 1);

           g.setFont(f);

           g.drawString(fontlist[i], , i * 20 +20);       

         }

     }

 }

467 FindingInformation on a Font

467 尋找一個字型的資訊

When your programs display text, there will be times when youneed to get information about the current font. For example, before you displaytext, you may need to test the current font size to make sure the text will fitwithin the window region you desire. To learn specifics about the current font,your programs must first use the Component class getFont method to get thecurrent Font object. Next, to get information about the current font, yourprogram can use the Font class methods listed in Table 467.

當你的程式顯示文字時,你有時會需要獲得當前字型的資訊. 例如,在你顯示文字前,你可能需要測試一下當前字型的大小, 以保證所寫的文字能寫在你所需的視窗區域內. 為了瞭解當前字型的細節, 你的程式必須先用Component 類的 getFont方法以取到當前的Font物件. 然後,為了獲得當前字型的資訊, 你的程式可以使用列於表467中的Font類方法. 

Method   Purpose

-----------------------------------------------------------

getName  Returns the name of the font

          返回字型名

getSize  Returns the point size of the font

          返回字型的點的大小

getStyle Returns the style of the font

          返回字型型別

isBold   Returns true if it is a bold font

          返回true, 如果字型為粗體

isItalic Returns true if it is a italic font

          返回true, 如果字型為斜體

isPlain  Returns true if it is a plain font

          返回true, 如果字型為普通體

-----------------------------------------------------------

Table 467 Font classmethods that return information about a font.

表467 返回字型資訊的Font類方法

The following init method displays the name, style, and size ofthe current font:

以下的init方法顯示當前字型的名稱,型別以及大小

public void init()

  {

    Font f = getFont();

    System.out.println(Name:  + f.getName());

    System.out.println(Style:  + f.getStyle());

    System.out.println(isBold:  + f.isBold());

    System.out.println(isItalic:  + f.isItalic());

    System.out.println(isPlain:  + f.isPlain());

    System.out.println(Size:  + f.getSize());

  }

468Understanding Font Metrics

468 瞭解字型點陣

In Tip 467, you learned how to use Font class methods to obtainthe current fonts point size. Before you learn how to gather more informationabout the current font metrics, such as the baseline and character width, youneed to better understand several key terms. Later, to correctly place text onthe screen, or to align text with other objects, you will need to takeadvantage of several font characteristics. Figure 468 will help you understandseveral key font metrics.

在TIP 467中, 你已知道了怎樣使用Font類方法來獲得當前字型的大小. 在你瞭解怎樣收集更多的當前字型資訊,諸如字元的基線(baseline),字元的寬度,等, 你必須首先更好地瞭解一些關鍵性的術語. 然後,為了把文字正確地寫到螢幕上去,或者將文字與其它的物件的位置對準, 你還需要利用幾個字型特性.圖468將幫助你瞭解字型的幾個主要特徵.

Figure 468 Fontmetrics parameters.

圖468 字型引數

469 How toGet Font Metrics Information

469 怎樣得到字型點陣資訊

In Tip 468, you learned about several key font characteristics.Using a FontMetrics object, your applets can get several of these metrics forthe current font. To create a FontMetrics object, you can use either thegetFontMetrics method or the FontMetrics(Font) constructor. Then, you can usethe FontMetrics class methods to find about specifics about the current font.Table 469 lists several of the FontMetrics methods.

在TIP 468中, 你已知道了幾種重要的字型特性. 利用FontMetrics 物件,你的應用程式可以得到有關當前字型的這些資訊. 為了建立FontMetrics 物件,可用getFontMetrics方法,或 FontMetrics(Font)建構函式. 然後,你可以用FontMetrics類方法來找到有關當前字型的說明. 表478 列出了幾種FontMetrics方法. 

Method                    Purpose

------------------------------------------------------------------------

getAscent()               Returns the ascent of the font

                          返回字型的上升量

getDescent()              Returns the descent of the font

                          返回字型的下降量

getLeading()              Returns the leading of the font

                          返回字型的左邊沿

getHeight()              Returns the height of the font

                          返回字型的高度

charWidth(char ch)        Returns the width of the characterspecified

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

                          Returns the width ofthe byte array

                          返回位元組陣列的寬度

stringWidth(String str)   Returns the width of the String

                          返回字串的寬度

------------------------------------------------------------------------

Table 469 SeveralFontMetrics methods.

表469 幾個FontMetrics 方法

For example, the following creates a FontMetrics object for thecurrent font, and then uses the charWidth method to return the pixel width ofthe 1-point Courier font letter C:

例如, 以下語句為當前字型建立了一個FontMetrics ,然後使用charWidth 方法來返回1點Courier體的字元C的象素寬度:

Font f = Font(Courier,Font.BOLD, 1);

FontMetrics fmetrics =new FontMetrics(f);

int len =fmetrics.charWidth(C);

470Underlining Your Text

470 在你的文字下加下劃線

Although the Java AWT library lets you create new fonts that usethe bold and italic style, Java does not support underlined text. However,using the FontMetrics class stringWidth() method, you can find the width of astring and underline the text yourself. The following applet, underline.java,underlines a string, as shown in Figure 470:

雖然Java AWT庫能讓你選用新字型, 使用粗體字, 斜體字, 恰Java 不支援下劃線的字元.但是, 利用FontMetrics 類的 stringWidth() 方法, 你可以找到字串的寬度,然後由你自己來加下劃線. 以下的應用程式,underline.java, 產生如圖470所示的一根下劃線.                        

import java.applet.*;

import java.awt.*;

public class underlineextends Applet {

   Font f1 = new Font("TimesRoman",Font.PLAIN, 1);

   String str = "This line is underlined";

   public void paint(Graphics g)

     {

       int strlen =getFontMetrics(f1).stringWidth(str);

       g.setFont(f1);

       g.drawString(str, , 30);

       // draw line to underline string

       g.drawLine(, 30 + 1,  + strlen, 30 + 1);

    }

 }

Figure 470 Underlinedtext string.

圖 470新增字串下劃線

471 Drawinga Line of Text with Multiple Fonts

471 用幾種字型來寫出一行字

Although Java lets you select different fonts for drawing text,it is a more challenging task if you want to display text using different fontsor if you want to draw two strings of the same font on the same line. After youdisplay the first string, you must find its ending screen location, andposition the second string at that point. The following applet,two_string.java, uses the stringWidth method to find the width of a string, andthen uses the width information to draw a line of text using multiple fonts, asshown in Figure 471:

Java雖然讓你選用不同的自字型來寫字, 但如果你想在文字中使用幾種不同的字型,或在同一行中用同一種字型寫出兩個字串, 仍是困難的事情. 當你顯示了第一個字串之後, 你必須找到該字串的結束點的螢幕位置, 並把第二個字元放在這一位置上.以下的應用程式two_string.java利用stringWidth方法來找出字串的寬度,然後利用寬度資訊來寫出包含多種字型的一行字,如圖471所示:

import java.applet.*;

import java.awt.*;

public classtwo_string extends Applet {

   Fontf1 = new Font("Helvetica", Font.BOLD, 18);

   Font f2 = new Font("Courier",Font.PLAIN, 12);

   Font f3 = new Font("TimesRoman",Font.BOLD + Font.ITALIC, 12);

   String s1 = "18pt-Bold Helvetica";

   String s2 = "and ";

   String s3 = "12pt-Bold-Italic TimesRoman ";

   public void paint(Graphics g)

     {

       int x = ;

       g.setColor(Color.blue);

       g.setFont(f1);

       g.drawString(s1, x, );

       x += getFontMetrics(f1).stringWidth(s1);

       g.setColor(Color.black);

       g.setFont(f2);

       g.drawString(s2, x, );

       x += getFontMetrics(f2).stringWidth(s2);

       g.setColor(Color.red);

       g.setFont(f3);

       g.drawString(s3, x, );

     }

 }

As you can see, the program increments the variable x, using thevariable to position each new string of text.

正如你所看到的, 程式將變數x的值不斷增加,利用它來定新字串的位置

Figure 471 Drawing a line of text with multiple fonts.

圖471 寫出一行包含多種字型的字

472Aligning Your Text

472 重排你的文字

Using the FontMetrics methods you examined in Tip 469, you canalign your text horizontally and vertically. In fact, as you will learn, havinga reusable class for drawing aligned text is quite handy. The following code,AlignedText.java, shows you how to build such a class. In this case, the codecreates the AlignedText class, which you can use within your other applets:

利用你在 TIP 469中考察的 FontMetrics 方法, 你可以把你的字串按水平或垂直方向排列. 事實上,正如你將瞭解的那樣, 為書寫排好的文字字元而規定一個可重用的類是方便的. 以下這一AlignedText.java程式說明你怎樣建立這一種類. 在此例子中所建立的類你可以用在你其它的應用程式中:

import java.awt.*;

public classAlignedText {

   // Define constants for setting textalignment

   public static final int LEFT = 0x00;

   public static final int RIGHT = 0x01;

   public static final int CENTER = 0x02;

   public static final int BASELINE = 0x00;

   public static final int TOP = 0x0;

   public static final int BOTTOM = 0x08;

   private int    alignmentType;

   public AlignedText()

     {

        alignmentType = LEFT | BASELINE; //default alignment

     }

   public void set_alignment(intalignment_type)

     {

        alignmentType = alignment_type;

     }

   public void drawString(Graphics g, StringaString , int x, int y)

     {

        FontMetrics fmetrics =g.getFontMetrics();

        int len =  fmetrics.stringWidth(aString);

        if ((alignmentType & RIGHT) != 0)

          x -= len;     // offset x for right alignment

        else if ((alignmentType & CENTER)!= 0)

          x -= len/2;   // offset x for center alignment

        if ((alignmentType & TOP) != 0)

          y += fmetrics.getAscent();   // offset y for top alignment

        else if((alignmentType & BOTTOM) !=0)

          y -= fmetrics.getDescent();  // offset y for bottom

                                       //alignment

        g.drawString(aString, x, y);

     }

 }

The AlignedText class lets you set the text alignment using theset_align method. You can set horizontal alignment with aligned_text.LEFT,aligned_text.RIGHT, or aligned_text.CENTER, as well as the vertical alignmentwith aligned_text.TOP, aligned_text.BOTTOM, and aligned_text.BASELINE. You canthen draw text using the AlignedText class drawString method. The followingapplet, aligntext_test.java, illustrates the use of the AlignedText class anddraws several text strings with different alignments, as shown in Figure 472:

AlignedText 類方法使你可利用set_align方法來設定文字的排列形式. 你可以利用aligned_text.LEFT,aligned_text.RIGHT, 或 aligned_text.CENTER 將text設成水平書寫方式, 也可利用aligned_text.TOP,aligned_text.BOTTOM, 和 aligned_text.BASELINE將text設成垂直的書寫方式. 然後你可利用AlignedText 類的 drawString方法來寫text. 

以下的應用程式 aligntext_test.java, 說明了AlignedText類的用法, 它還利用不同的排列方式寫出了幾個字串,如圖472所示:

import java.awt.*;

import java.applet.*;

public classaligntext_test extends Applet {

   AlignedText aligned_txt = new AlignedText();

   public void paint(Graphics g)

    {

      aligned_txt = new AlignedText();

      g.setColor(Color.black);

      g.drawLine(, 0, , 100);

      g.setColor(Color.blue);

     aligned_txt.set_alignment(aligned_txt.LEFT);

      aligned_txt.drawString(g,"left", , 30);

     aligned_txt.set_alignment(aligned_txt.CENTER);

      aligned_txt.drawString(g,"center", , 60);

     aligned_txt.set_alignment(aligned_txt.RIGHT);

      aligned_txt.drawString(g,"right",  , 90);

      g.setColor(Color.black);

      g.drawLine(100, , 300, );

      g.setColor(Color.blue);

      aligned_txt.set_alignment(aligned_txt.BOTTOM);

      aligned_txt.drawString(g,"bottom", 100, );

     aligned_txt.set_alignment(aligned_txt.BASELINE);

      aligned_txt.drawString(g,"baseline", 160, );

     aligned_txt.set_alignment(aligned_txt.TOP);

      aligned_txt.drawString(g, "top",220, );

    }

}

Figure 472 Text strings with different alignments.

圖472 用不同形式排列的文字字串

473 Gettinga GIF Image File from the Web

473 從Web得到一個GIF圖象檔案

The days of text-only Web pages are long gone. Todays Web pagesare loaded with GIF and JPEG images. You can also display GIF and JPEG imagefiles within your Java applets. Displaying an image file in Java involves twosteps: getting the image and drawing the image. To get a GIF or JPEG image filewithin a Java applet is a simple a matter of calling one of the followinggetImage methods:

只有文字的 Web頁面時代早以過去了.  當今的Web頁面是用GIF和JPEG影象裝入的.在你的應用程式中你也可以裝入和顯示GIF和JPEG影象. 在Java中顯示一個影象檔案包括兩個步驟: 獲得影象和顯示影象. 為了在Java應用程式中得到一個GIF影象檔案或JPEG影象檔案,只需簡單地呼叫以下的getImage方法:

Image getImage(URLurl);

Image getImage(URLurl, String name);

Within the first getImage method, the url parameter must be aUniform Reference Locator (URL) that points to an image file on the Web. ThegetImage method returns an Image object that your program can later use toreference the GIF or JPEG image. For example, the following statement createsan Image object for the file sample.gif which resides on the server at,http://www.myserver.com:

在第一個getImage方法中, url引數必須是一個在Web上指向一個影象的 URL(Uniform Reference Locator,統一參考定位器). getImage方法返回一個你在此後可以用來引用的 GIF 或 JPEG 檔案. 例如,以下的語句為駐留在伺服器http://www.myserver.com上的sample.gif檔案建立了一個影象物件.

Image img =getImage(new URL(http://www.abc.com/ sample.gif));

Notice the hardcoded pathname in this example. As a rule, it isnot good programming to hardcode the servers name within the source file.Should you later need to move the image file to a different server, you willneed to change the source code to match the servers location and recompile.Instead, your applet can use the getCodeBase method to locate an image file.With the second getImage method, the url parameter points to the location wherethe image file is and the name parameter specifies the name of the image file.For example, the following statement uses the getCodeBase method to get the serverand directory location that corresponds to the applet file and then uses thatlocation to locate the file sample.gif:

請注意例子中硬性規定的路徑名(hardcoded pathname). 作為一個規則,把硬性規定的路徑名放進一個源程式中不是一種好的程式設計方法. 假如你以後要把影象檔案移到另一不同的伺服器中,你將需要改變源程式來匹配伺服器地址並重新編譯一次. 與此相反, 你的程式可用 getCodeBase 方法來確定圖象檔案的地址. 利用第二種getImage方法,url引數將指向檔案所在的地址,而名字引數指出檔案的名字. 例如,以