Synchronized로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

Synchronized로 검색한 결과
등록일:2008-03-13 14:09:37
작성자:
제목:Graphics




1.    Graphics


이  번  장에는  앞  장에서  배웠던  AWT를  효과적으로  지원해주는  Graphics에  대하여  배워  보자.  아마  AWT에서  본  내용들이  많이  나오고,  또  이  Graphics에서  나오는  내용들은  여러분들이  기본적으로  사용하는  내용들이  많아  무심히  넘어갈  수도  있는  내용들이다.  하지만  많이  그리고  자세히  알고  넘어간다면  많은  도움이  된다.  다음  장에  나오는  Applet에서도  많이  사용되는  내용이다.

중  요한  내용들을  잠깐  보고  갈까?  이  번  장에  나오는  내용은  글씨에  대한  여러  가지  정보와  특성을  나타내는  Font  클래스,  도형의  색을  나타내거나,  글씨의  색을  표현하는  Color  클래스  ,  여러  가지  도형을  그릴  때  사용되는  Graphics,  또  Graphics  클래스를  더욱  발전시켜  보기  좋게  만들어  주는  2D  Graphics,  이미지  load시  필요한,  Object  클래스의  wait()  메서드가  생각나는  MediaTracker  클래스  ,  그리고  여러  가지  Image를  load시키는  방법이다.  이렇게  써놓고  보니  도움  정도가  아니라  꼭  필요한  내용들이다.  그리고  다음  장에서  배울  Applet도  맛배기로  등장한다.  자  그럼  내용들로  들어가  보자.  


1.1.    Font  클래스


Font  클래스는  시스템에서  제공하는  글꼴을  사용하는  것으로서  글꼴의  속성과  스타일을  정의한다.  폰트의  스타일로  기본  스타일과  굵기체  ,  기울기  체  등을  제공하는데  굵은체이면서  이탤릭체와  같이  서로  조합해서  사용할  수  있다.  예를  들면,  Font.ITALIC  +  Font.BOLD와  같이  사용할  수  있다.  자바에서  제공하는  Font  클래스를  사용하기  위해서는  java.awt.font  패키지를  import해야  한다.  그런데  AWT와  같이  사용한다면  java.awt  패키지만  import  해주면  된다.


Font  클래스의  사용법은  다음과  같다.

폰트를  생성하기  위해서  폰트의  이름,  스타일,  글자크기를  정한다.

Font  f  =  new  Font(“Batang”,  Font.ITALIC  +  Font.BOLD,  12);


이렇게  생성된  폰트를  Graphics  클래스의  객체  g를  생성하여  g.setFont()  메서드를  이용해서  설정한다.

g.setFont(매개변수);  


그럼  다음  예제를  통해서  Graphics  클래스를  이용해  Font  클래스가  제공하는  폰트의  스타일들을  어떻게  지정하는지  보자.


FontTest.java(Font  클래스를  테스트하기  위한  예제)

import  java.awt.*;

import  java.awt.Font;

import  java.awt.Graphics;

public  class  FontTest  extends  Frame  {  

      private  Font  font1,  font2,  font3;      

      public  void  paint(Graphics  g)  {

              setTitle("FontTest");

          font1  =  new  Font("Serif",  Font.BOLD,  12);

          font2  =  new  Font("Batang",  Font.ITALIC  +  Font.BOLD,  24);

          font3  =  new  Font("SansSerif",  Font.PLAIN,  14);

              g.setFont(font1);

              g.drawString("Serif  12  point  bold.",  20,  80);

            g.setFont(font2);

              g.drawString("바탕  24  point  italic.",  20,  45);

              g.setFont(font3);

              g.drawString("SansSerif  14  point  plain.",  20,  60);      

      }

      public  static  void  main(String[]  args)  {

              FontTest  f  =  new  FontTest();

              f.setSize(300,  100);

              f.setVisible(true);

      }

}

C:\JavaExample\14>javac  FontTest.java

C:\JavaExample\14>java  FontTest

  

결과를  보면  어려운  예제는  아니라고  생각한다.  예제를  보면,  import를  확실히  하기  위해  클래스별로  import시켰다.

import  java.awt.Font;

import  java.awt.Graphics;


위의  두  구문은  생략해도  상관없다.  먼저  Font  클래스를  이용해  생성한  객체  font1에  글꼴(“Serif”)을  설정하고  Font  클래스의  생성자  메서드에  속성과  글자크기를  할당한다.

Font  font1  =  new  Font("Serif",  Font.BOLD,  12);


paint(Graphics  g)  메서드를  호출하는  순간  Graphics  클래스의  객체  g가  생성되어  멤버  메서드인  setFont()  메서드를  이용해  폰트를  설정한다.

g.setFont(font1);


그리고  g.drawString()  메서드를  이용해서  프레임에  문자열을  (20,  80)위치에  출력한다.

g.drawString("Serif  12  point  bold.",  20,  80);


같은  방법으로  다른  글씨와  크기,  폰트를  바꾸어서  출력을  하였다.


☞  Font  클래스

Font  font  =  new  Font(String  name,  int  style,  int  size);

String  name  :  글꼴의  이름

int  style  :  글꼴의  스타일

int  size  :  글자의  크기


폰트를  사용하다  보면  글자가  깨지거나  자기가  지정한  글꼴로  안  나오는  경우가  있다.

이  것은  시스템이  지원하는  폰트가  다르기  때문이다.  이  문제를  해결하기  위해서  JDK에서는  영문의  표준으로  Serif,  Monospaced,  SansSerif,  Dialog,  DialogInput  폰트에  한해서  동일한  모양을  유지시키고  있다.  가능하면  이  폰트를  디폴트로  사용하는  것이  좋다.  한글은  바탕,  바탕체,  굴림  등과  같은  글씨체를  쓰는  편이  좋을  것이다.


Font  생성자  메서드

■  public  Font(String  name,  int  style,  int  size)  :  지정된  이름,  양식,  크기로  새로운  글꼴을  작성한다.


Font  주요  멤버필드

■  public  final  static  int  PLAIN  :  평범한  스타일의  글꼴을  나타내는  변수

■  public  final  static  int  BOLD  :  굵은  스타일의  글꼴을  나타내는  변수

■  public  final  static  int  ITALIC  :  이탤릭체  스타일의  글꼴을  나타내는  변수


Font  주요  멤버  메서드

■  public  static  Font  decode(String  str)  :  인자로  전달된  명칭  str을  사용해  그에  맞는  폰트를  구한다.      

■  public  String  getFontName()  :  폰트  이름을  얻어낸다.

■  public  String  getFamily()  :  현재의  폰트가  소속되어  있는  폰트  패밀리의  이름을  리턴하는데  정확한  폰트  패밀리의  이름은  시스템마다  다르다.

■  public  String  getName()  :  폰트의  이름을  문자열로  리턴한다.

■  public  int  getStyle()  :  현재  폰트의  스타일을  정수값으로  리턴한다.  이  정수들은  Font  클래스에  이미  정의되어  있는  상수들로써,  Font.PLAIN,  Font.ITALIC,  Font.BOLD과  같은  값이며  혹은  이들이  조합된  정수값이다.

■  public  int  getSize()  :  폰트  크기를  포인트(point)  단위로  리턴한다.


1.2.    Color  클래스


앞  선  Font  클래스에  이어  이번에는  Color  클래스에  대하여  알아보자.  이  Color  클래스는  설명할  것도  없을  정도로  쉬워  보이지  않나?  바로  색깔에  관련된  클래스이다.  도형의  색깔을  나타내거나,  글씨의  색깔을  나타내는  클래스이다.  간단한  예제를  보자.


ColorTest.java(Color  클래스는  테스트하기  위한  예제)

import  java.awt.*;

public  class  ColorTest  {

      public  static  void  main(String[]  args)  {

              int  a,b,c;

              a  =  Integer.parseInt(args[0]);

              b  =  Integer.parseInt(args[1]);

              c  =  Integer.parseInt(args[2]);

              Frame  f  =  new  Frame();

              f.setSize(100,100);

            f.setBackground(new  Color(a,b,c));

              f.setVisible(true);

      }

}


C:\JavaExample\14>javac  ColorTest.java

C:\JavaExample\14>java  ColorTest  125  125  125


  


위의  예제는  Frame에  색깔을  넣는  예제이다.  예제를  보면  이해할  것이다.

먼저  컴파일을  한  후  프로그램을  실행  시킬  때  색의  숫자를  입력해야  한다.  숫자는  0부터  255  사이의  값을  넣어야  한다.

int  a  =  Integer.parseInt(args[0]);

int  b  =  Integer.parseInt(args[1]);

int  c  =  Integer.parseInt(args[2]);


받아온  값을  int형으로  변환시켜  Color  클래스의  생성자  메서드의  매개변수로  넣어준다.

f.setBackground(new  Color(a,b,c));


setBackground()  메서드는  배경  색을  나타내  주는  메서드인거  알고  있을  것이다.  이  메서드는  매개변수로  받은  값들을  혼합하여  Frame의  배경  색을  나타내  준다.  여기서  a는  Red를  나타내고,  b는  Green을  나타내며,  c는  Blue를  나타낸다.  즉  a가  0이면  빨강빛이고,  255면  하얀빛을  나타낸다.  (0,  0,  0)이면  검정색이고,  (255,  255,  255)는  하얀색이다.  그리고  조금  더  말씀드리면  빨강색은  (255,  0,  0),  초록색은  (0,  255,  0),  파랑색은  (0,  0,  255)이다.  보통  흔히  말하는  RGB라는  것은  Red,    Green,    Blue이  세  가지  색을  혼합하는  것을  말한다.  위의  예제를  숫자를  바꾸어  보면서  테스트  해보면  금방  이해할  수  있을  것이다.


☞  Color  클래스

RGB  형식을  사용하여  색을  캡슐화(encapsulate)한다.

RGB  형식으로  빨강,  파랑,  초록  컴포넌트는  각각  0-255  사이의  정수로  표시된다.

0  값은  기본  색상이  전혀  포함되지  않음을  나타내고,  255  값은  이  색상  컴포넌트의  최대  강도를  나타낸다.


Color  멤버필드

■  public  static  Color  black  :  black을  나타낸다.

■  public  static  Color  blue  :  blue를  나타낸다.

■  public  static  Color  cyan  ;  cyan을  나타낸다.

■  public  static  Color  darkGray  :  darkGray를  나타낸다.

■  public  static  Color  gray  :  gray를  나타낸다.

■  public  static  Color  green  :  green을  나타낸다.

■  public  static  Color  lightGray  :  lightGray를  나타낸다.

■  public  static  Color  magenta  :  magenta를  나타낸다.

■  public  static  Color  orange  :  orange를  나타낸다.

■  public  static  Color  pink  :  pink를  나타낸다.

■  public  static  Color  red  :  red를  나타낸다.

■  public  static  Color  white  :  white를  나타낸다.

■  public  static  Color  yellow  :  yellow를  나타낸다.


Color  생성자  메서드

■  public  Color  (ColorSpace  cspace,  float[]  components,  float  alpha)  :  float  배열로  지정된  색성분과  지정된  알파를  사용해  지정된  ColorSpace의  색을  작성한다.  

■  public  Color  (float  r,  float  g,  float  b)  :  범위  (0.0  -  1.0)의  지정된  빨강,  초록,  파랑의  값을  사용해  불투명한  sRGB  칼라를  작성한다.

■  public  Color  (float  r,  float  g,  float  b,  float  a)  :    범위  (0.0  ~  1.0)의  지정된  빨강,  초록,  파랑  및  알파의  값을  사용해  sRGB  칼라를  작성한다.  

■  public  Color  (int  rgb)  :    비트  16-23  의  적색  성분,  비트  8-15  의  녹색  성분  및  비트  0-7의  청색  성분으로부터  합성된,  지정된  RGB  값을  사용해  불투명한  sRGB  칼라를  작성한다.  

■  public  Color  (int  rgba,  boolean  hasalpha)  :    비트  24  ~  31의  알파  성분,  비트  16  ~  23의  적색  성분,  비트  8  ~  15의  녹색  성분  및  비트  0  ~  7의  청색  성분으로  구성되는,  지정된  RGBA  값을  가지는  sRGB  칼라를  작성한다.

■  public  Color  (int  r,  int  g,  int  b)  :    범위  (0  ~  255)의  지정된  빨강,  초록,  파랑의  값을  사용해  불투명한  sRGB  칼라를  작성한다.  

■  public  Color  (int  r,  int  g,  int  b,  int  a)  :  범위  (0  -  255)의  지정된  빨강,  초록,  파랑  및  알파값을  사용해  sRGB  칼라를  작성한다.


Color  주요  멤버  메서드

■  public  Color  brighter  ()  :  이  Color를  보다  밝게  한,  새로운  Color를  작성한다.  

■  public  PaintContext    createContext(ColorModel    cm,  Rectangle    r,  Rectangle2D    r2d,  AffineTransform    xform,  RenderingHints  hints)  :  솔리드  칼라  패턴을  작성하기  위해서  사용되는  PaintContext를  작성해  돌려준다.  

■  public  Color  darker  ()  :    이  Color를  보다  어둡게  한,  새로운  Color를  작성한다.  

■  public  static  Color  decode  (String    nm)  :  String을  정수값으로  변환해,  지정된  불투명한  Color를  돌려준다.  

■  public  boolean  equals  (Object  obj)  :  다른  Object가  이  Color와  같은지  어떤지를  판정  한다.  

■  public  int  getAlpha  ()  :  0  ~  255  의  범위에  있는  알파  성분을  돌려준다.

■  public  int  getBlue  ()  :  Default의  sRGB  영역의  0  ~  255  의  범위에  있는  파랑색  성분을  돌려준다.  

■  public  static  Color  getColor  (String  nm)  :  시스템  특성에서  색을  검색한다.  

■  public  static  Color  getColor  (String  nm,  Color    v)  :    시스템  특성에서  색을  검색한다.  

■  public  static  Color  getColor  (String  nm,  int  v)  :    시스템  특성에서  색을  검색한다.  

■  public  float[]  getColorComponents  (ColorSpace  cspace,  float[]  compArray)  :  cspace  파라미터에  의해  지정된  ColorSpace로  나타내지는  Color의  색성분만큼을  격납  하는  float  배열을  돌려준다.  

■  public  float[]  getColorComponents  (float[]  compArray)  :  Color의  ColorSpace로  나타나는  Color의  색성분만큼을  격납하는  float  배열을  돌려준다.  

■  public  ColorSpace  getColorSpace  ()  :  이  Color의  ColorSpace를  돌려준다.  

■  public  float[]  getComponents  (ColorSpace  cspace,  float[]  compArray)  :  cspace  파라미터에  의해  지정된  ColorSpace로  나타내지는  Color의  색성분  및  알파  성분을  격납  하는  float배열을  돌려준다.  

■  public  float[]  getComponents  (float[]  compArray)  :  Color의  ColorSpace로  나타내지는  Color의  색성분  및  알파  성분을  격납하는  float  배열을  돌려준다.  

■  public  int  getGreen  ()  :    디폴트의  sRGB  영역의  0  ~  255  의  범위에  있는  초록색  성분을  돌려준다.  

■  public  static  Color  getHSBColor  (float  h,  float  s,  float  b)  :  HSB  칼라  모델에  지정된  값에  근거해  Color  Object를  작성한다.  

■  public  int  getRed  ()  :  Default의  sRGB  영역의  0  ~  255의  범위에  있는  빨강색  성분을  돌려준다.  

■  public  int  getRGB  ()  :  Default의  sRGB  ColorModel의  색을  나타내는  RGB값을  돌려준다(비트  중  24  ~  31  은  알파,  16  ~  23은  빨강,  8  ~  15는  초록,  0  ~  7은  파랑).

■  public  float[]  getRGBColorComponents  (float[]  compArray)  :    디폴트의  sRGB  칼라  영역에서  나타내지는  Color의  색성분만큼을  포함  하는  float배열을  돌려준다.  

■  public  float[]  getRGBComponents  (float[]  compArray)  :    디폴트의  sRGB  칼라  영역에서  나타내지는  Color의  색성분  및  알파  성분을  포함  하는  float배열을  돌려준다.  

■  public  int  getTransparency  ()  :  이  Color의  투명도  모드를  돌려준다.  

■  public  int  hashCode  ()  :  이  Color의  hash  code  value를  계산한다.  

■  public  static  int  HSBtoRGB  (float  hue,  float  saturation,  float  brightness)  :    HSB  모델에  의해  지정되는  색의  성분을,  대응하는  디폴트의  RGB  모델의  값세트로  변환한다.  

■  public  static  float[]  RGBtoHSB  (int  r,  int  g,  int  b,  float[]  hsbvals)  :  디폴트의  RGB  모델에  의해  지정된  색의  성분을,  HSB  모델의  3  개의  성분인  색상,  채도,  명도의  값의  대응하는  세트로  변환한다.  

■  public  String  toString  ()  :    이  Color의  캐릭터  라인  표현을  돌려준다.



1.3.    Graphics  클래스


Graphics  클래스는  그림에  관련된  프로그램을  작성하는  데  꼭  필요한  클래스이다.  여러  가지  도형을  그릴  수  있는  메서드들이  들어  있다.  이  Graphics  클래스는  보통  다른  클래스의  paint()  메서드  안에서  객체가  생성되고,  그  객체를  이용하여  Graphics  클래스의  멤버  메서드가  호출되어  사용된다.

우  리가  많이  사용하는  도형들을  보면  Rectangle(사각형),  Oval(원형),  Polygon(다각형),  Line(선)들이  있다.  그리고  글씨  그리기,  구역  복사하기,  구역  삭제하기에  대해서  알아보자.  아래의  예제는  Graphics의  여러  메서드들을  호출하여  Canvas에  도형들을  그린  후,  Canvas를  Frame에  부착하는  예제이다.  그럼  예제를  테스트  해보자.


GraphicsTest.java  (Graphics  클래스를  테스트하기  위한  예제)

import  java.awt.*;

public  class  GraphicsTest  extends  Frame  {

      public  GraphicsTest()  {

            add(new  Canvas()  {

                  public  void  paint(Graphics  g)  {

                        g.setColor(Color.red);

                        g.draw3DRect(    0,  0,  46,  36,  true);

                        g.drawOval(50,  0,  46,  36);

                        int  x1[]  =  new  int[]  {  100,  300,  273  };

                        int  y1[]  =  new  int[]  {      0,      0,    36  };

                        g.drawPolygon(x1,  y1,  x1.length);

                        g.setColor(Color.blue);

                        g.fill3DRect(    0,  40,  46,  36,  true);

                        g.fillOval(50,  40,  46,  36);

                        int  x2[]  =  new  int[]  {  100,  300,  273  };

                        int  y2[]  =  new  int[]  {    40,    40,    76  };

                        g.fillPolygon(x2,  y2,  x2.length);

                        g.drawLine(150,  40,  396,  76);

                        g.setColor(Color.black);

                        g.drawString("www.jabook.org",  10,  115);

                        g.setColor(Color.cyan);

                        g.drawRoundRect(  0,  120,  46,  36,  10,  10);

                        g.fillRoundRect(50,  120,  46,  36,  10,  10);

                        g.clearRect(30,  30,  250,  30);

                  }

            });

      }

      public  static  void  main(String  args[])  {

            GraphicsTest  f  =  new  GraphicsTest();

            f.setTitle("Graphics");

            f.setSize(420,  200);

            f.setVisible(true);

      }

}

    

C:\JavaExample\14>javac  GraphicsTest.java

C:\JavaExample\14>java  GraphicsTest


  


위의  예제는  Canvas에  Graphics  클래스의  객체를  생성하여  Graphics  클래스의  여러  멤버  메서드들을  호출하여  여러  모양의  도형들을  그려본  예제이다.

Graphics  클래스의  객체는  Canvas의  paint(Graphics  g)  메서드가  생성하였다.

public  void  paint(Graphics  g)  


생성한  객체  g를  이용하여  g.setColor(Color  c)  메서드를  사용해  생성될  도형의  색깔을  지정한다.  다시  색을  지정할  때까지  같은  색의  도형이나  글씨가  출력된다.

g.setColor(Color.red);


사  각형을  그리는  메서드는  g.draw3DRect(int  x,  inty,  int  width,  int  height,  boolean  raised)와  g.drawRect(int  x,  int  y,  int  width,  int  height)가  있다.  먼저  나온  메서드는  사각형을  3D로  그려주고,  뒤에  나온  메서드는  사각형을  2D로  그린다.  그럼  메서드의  매개변수에  대하여  설명  하겠다.

■  int  x                                :  사각형이  시작하는  x좌표를  나타낸다.

■  int  y                                :  사각형이  시작하는  y좌표를  나타낸다.

■  int  width        :  사각형의  가로길이를  나타낸다.

■  int  height        :  사각형의  세로길이를  나타낸다.

■  boolean  raised              :  사각형이  영역  위로  올라오는지  영역  아래로  가라앉는지를  나타낸다.  (draw3DRect()  메서드)

■  boolean  raised  :  사각형이  영역  위로  올라오는지  아니면  표면이  에칭(etching)되는  지를  나타낸다.  (fill3DRect()  메서드)


g.fill3DRect(int  x,  int  y,  int  width,  int  height,  boolean  raised)와  g.fillRect(int  x,  int  y,  int  width,  int  height)  메서드  또한  사각형을  그리는  메서드이다.  다만  사각형의  내부를  꽉  채워  출력한다.

g.draw3DRect(0,  0,  46,  36,  true);

g.fill3DRect(0,  40,  46,  36,  true);

g.drawRect(50,  160,  300,  100);

g.drawRoundRect(0,  120,  46,  36,  10,  10);

g.fillRoundRect(50,  120,  46,  36,  10,  10);


위  의  구문  중  g.drawRoundRect(int  x,  int  y,  int  width,  int  height,  int  arcWidth,  int  arcHeight)  메서드는  모서리와  모서리가  만나는  각을  rounding  처리하는  매개변수의  값을  더  요구  한다.  Rectangle을  그리는  메서드들의  매개변수들은  거의  비슷하다.  그래서  한  번  읽어보고  API를  참조해서  사용하면  별로  지장이  없을  듯  싶다.  별로  어려울  것이  없다.


Rectangle을  그리는  메서드들의  매개변수

■  int  x  :  사각형이  시작하는  x  좌표를  나타낸다.

■  int  y  :  사각형이  시작하는  y  좌표를  나타낸다.

■  int  width  :  사각형의  가로  길이를  나타낸다.

■  int  height  :  사각형의  세로  길이를  나타낸다.

■  boolean  raised  :  사각형이  영역  위로  올라오는지  영역  아래로  가라앉는지를  나타낸다(draw3DRect()  메서드).

■  boolean  raised  :  사각형이  영역  위로  올라오는지  영역으로  에칭(etching)되는지를  나타낸다(fill3DRect()  메서드).

■  int  arcWidth  :  네  모서리에서  호의  수평  직경을  나타낸다.

■  int  arcHeight  :  네  모서리에서  호의  수직  직경을  나타낸다.



다음으로,  원과  타원을  그리는  메서드들을  보자.

■  g.drawOval(50,  0,  46,  36);

■  g.fillOval(50,  40,  46,  36);


위의  구문에서  위의  메서드는  속이  빈  원이  그려지고,  아래의  메서드는  속이  찬  원이  그려지게  된다.  drawOval(int  x,  int  y,  int  width,  int  height)  메서드를  보면서  설명한다.

■  int  x  :  원  중심의  x좌표를  나타낸다.

■  int  y  :  원  중심의  y좌표를  나타낸다.

■  int  width  :  원의  가로길이를  나타낸다.

■  int  height  :  원의  세로길이를  나타낸다.


width와  height가  같게  되면  원이  되고,  다르면  타원이  된다.


Oval을  그리는  메서드들의  매개변수  

■  int  x  :  원  중심의  x좌표를  나타낸다.

■  int  y  :  원  중심의  y좌표를  나타낸다.

■  int  width  :  원의  가로  길이를  나타낸다.

■  int  height  :  원의  세로  길이를  나타낸다.


width와  height가  같게  되면  원이  되고,  다르면  타원이  된다.


다음은  다각형을  그리는  메서드를  보자.  위의  예제에서는  삼각형을  그려보았다.

int  x1[]  =  new  int[]  100,  300,  273;

int  y1[]  =  new  int[]  0,  0,  36;

g.drawPolygon(x1,  y1,  x1.length);

int  x2[]  =  new  int[]  100,  300,  273;

int  y2[]  =  new  int[]  40,  40,  76;

g.drawPolygon(x2,  y2,  x2.length);


위  의  메서드는  속이  빈  삼각형이  그려지고,  아래의  메서드는  속이  찬  삼각형이  그려진다.  배열에  점이  3개  밖에  없다.  그래서  삼각형이  그려진다.  drawPolyline(int[]  xPoints,  int[]  yPoints,  int  nPoints)  메서드를  보면서  설명한다.

■  int[]  xPoints  :  x의  좌표값들을  모은  배열

■  int[]  yPoints  :  y의  좌표값들을  모은  배열

■  int  nPoints  :  점의  갯수


이  메서드는  매개변수로  포함된  점들을  연결한  다각형을  그리는  것이다.  다시  한번  말하지만  점이  3개여서  삼각형이  그려진  것이다.  왜  삼각형  그리는  메서드는  없냐고  불평해도  소용없다.  Sun사에서  지원을  안  하니깐.


Polygon을  그리는  메서드들의  매개변수

■  int[]  xPoints  :  x의  좌표값들을  모은  배열을  나타낸다

■  int[]  yPoints  :  y의  좌표값들을  모은  배열을  나타낸다

■  int  nPoints  :  점의  개수를  나타낸다


그리고  선을  그리는  메서드가  있다.

■  g.drawLine(150,  40,  396,  76);


이  메서드의  원형은  drawLine(int  x1,  int  y1,  int  x2,  int  y2)이다.

■  int  x1  :  시작점의  x좌표를  나타낸다.

■  int  y1  :  시작점의  y좌표를  나타낸다.

■  int  x2  :  끝점의  x좌표를  나타낸다.

■  int  y2  :  끝점의  x좌표를  나타낸다.


네  개의  좌표로서  생긴  두  점을  연결하면  선이  그려진다.


Line을  그리는  메서드의  매개변수

■  int  x1  :  시작점의  x좌표를  나타낸다.

■  int  y1  :  시작점의  y좌표를  나타낸다.

■  int  x2  :  끝점의    x  좌표를  나타낸다.

■  int  y2  :  끝점의    x  좌표를  나타낸다


그리고  글씨를  그릴  수  있다.

■  g.drawString("www.jabook.org",  10,  115);  :  이  메서드는  “www.jabook.org”라는  글을  Canvas에  그렸다.  메서드의  원형은  drawString(String  str,  int  x,  int  y)이다.

■  String  str  :  그려질  글씨이다.

■  int  x  :  글씨가  그려질  x좌표의  위치이다.

■  int  y  :  글씨가  그려질  y좌표의  위치이다.


글씨를  그린다고  생각하면  우스울지도  모르지만  사실  그린다는  개념이  맞다.  그러나  글씨를  그리든지  쓰든지  잘  나오기만  하면  되는  것이다.


String을  그리는  메서드의  매개변수

■  String  str  :  그려질  글씨를  나타낸다.

■  int  x  :  글씨가  그려질  x좌표의  위치이다.

■  int  y  :  글씨가  그려질  y좌표의  위치이다.


구역을  지우는  메서드도  있다.  바로  clearRect(int  x,  int  y,  int  width,  int  height)  메서드이다.

■  int  x  :  사각형이  시작하는  x좌표를  나타낸다.

■  int  y  :  사각형이  시작하는  y좌표를  나타낸다.

■  int  width  :  사각형의  가로  길이를  나타낸다.

■  int  height  :  사각형의  세로  길이를  나타낸다.


만들어진  사각형만큼의  구역을  삭제한다.

■  g.clearRect(80,  180,  250,  30);


clearRect()  메서드의  매개변수  

■  int  x  :  사각형이  시작하는  x좌표를  나타낸다.

■  int  y  :  사각형이  시작하는  y좌표를  나타낸다.

■  int  width  :  사각형의  가로길이를  나타낸다.

■  int  height  :  사각형의  세로길이를  나타낸다.


구역을  복사하는  메서드도  있다.  그런데  그  구역은  네모난  구역만  복사  된다.  한  번  예제를  보고나서  설명을  하겠다.  별로  어렵지는  않는다.


CopyAreaTest.java(copyArea()  메서드를  테스트하기  위한  예제)

import  java.awt.*;

public  class  CopyAreaTest  extends  Frame  {

      public  CopyAreaTest()  {

              add(new  Canvas()  {

                    public  void  paint(Graphics  g)  {

                          g.setColor(Color.blue);

                          g.drawString("www.jabook.org",  10,  15);

                        g.copyArea(  0,  0,  100,  20,  100,  0);

                    g.copyArea(  0,  0,  100,  20,  0,  30);

                    g.copyArea(  0,  0,  100,  20,  100,  30);

                    }

              });

      }

      public  static  void  main(String  args[])  {

              CopyAreaTest  f  =  new  CopyAreaTest();

              f.setTitle("CopyAreaTest");

              f.setSize(220,  80);

              f.setVisible(true);

      }

}

C:\JavaExample\14>javac  CopyAreaTest.java

C:\JavaExample\14>java  CopyAreaTest

  



위의  예제는  글씨를  그린  다음,  일정  구역을  복사  한  다음  그  구역을  다른  곳에  붙이는  예제이다.  “www.jabook.org”라는  글을  (10,  15)  지점에  그린  것은  알  것이다.

g.setColor(Color.blue);

g.drawString("www.jabook.org",  10,  15);


글은  파란색으로  그렸다.  그리고  바로  다음에  구역을  복사하는  메서드인  copyArea()  메서드가  나온다.

g.copyArea(  0,  0,  100,  20,  100,  0);

g.copyArea(  0,  0,  100,  20,  0,  30);

g.copyArea(  0,  0,  100,  20,  100,  30);


이  제  매개변수를  보면  예상이  되지  않나?  아직  아닌가?  메서드의  원형을  보면서  설명하겠다.  abstract  void  copyArea(int  x,  int  y,  int  width,  int  height,  int  dx,  int  dy)  메서드이다.  이  메서드는  다른  메서드와  달리  추상메서드이므로  사용할  때는  상속을  받아  몸체를  구현해야  한다.

■  int  x  :  복사가  시작되는  x좌표를  나타낸다.

■  int  y  :  복사가  시작되는  y좌표를  나타낸다.

■  int  width  :  시작점의  위치에서  사각형의가로  길이를  나타낸다.

■  int  height  :  시작점의  위치에서  사각형의  세로  길이를  나타낸다.

■  int  dx  :  픽셀을  복사할  수평  거리를  나타낸다.

■  int  dy  :  픽셀을  복사할  수직  거리를  나타낸다.


위  의  메서드는  결국  (0,  0)의  점부터  가로의  길이로  100,  세로의  길이로  30만큼의  구역을  복사하여,  가로로  100  떨어진  지점부터,  세로는  0만큼  떨어진  지점으로  이동해서  다시  그리라는  뜻이다.  아래의  두  구문들은  가로로  0,  세로로  30  이동하라는  뜻과  가로로  100,  세로로  30  이동하라는  뜻이다.  가로로  dx만큼  떨어진  거리에  세로로  dy만큼  떨어진  거리에  복사한  구역을  그리는  거죠.  dx,  dy가  음의  값을  가질  경우  왼쪽과  위로  움직여  그리라는  뜻이다.


copyArea()  메서드의  매개변수  

■  int  x  :  복사가  시작되는  x  좌표를  나타낸다.

■  int  y  :  복사가  시작되는  y  좌표를  나타낸다.

■  int  width  :  시작점의  위치에서  사각형의  가로  길이를  나타낸다.

■  int  height  :  시작점의  위치에서  사각형의  세로  길이를  나타낸다.

■  int  dx  :  픽셀을  복사할  수평  거리를  나타낸다.

■  int  dy  :  픽셀을  복사할  수직  거리를  나타낸다.


위에  설명한  메서드들은  그래픽에서  많이  쓰여지는  메서드들이다.  이외에  자바에서  그래픽을  지원하는  메서드는  많이  있다.  아래에  주요  멤버  메서드에  대하여  설명하였으니  꼭  읽어  보고  가야  한다.

Graphics  클래스는  오로지  그림만을  위해서  존재하는  클래스이다.  이  클래스가  있어서  사용자가  그래픽  작업을  편하게  할  수  있다.  하지만  메서드가  많이  존재하는  클래스이다.  능력이  된다면,  전부  암기를  하는  것도  좋지만  API를  보고  사용하는  데  지장이  없을  정도만  이해하고  넘어가도  아무  문제는  없다.


Graphics  주요  멤버  메서드

■  public  abstract  void  clearRect(int  x,  int  y,  int  width,  int  height)  :  주어진  사각형을  배경색으로  지운다.

■  public  abstract  void  clipRect(int  x,  int  y,  int  width,  int  height)  :  주어진  사각형을  잘라서  현재  클립에  저장한다.

■  public  abstract  void  copyArea(int  x,  int  y,  int  width,  int  height,  int  dx,  int  dy)  :  컴포넌트의  주어진  영역을  dx와  dy  거리만큼에  복사한다.

■  public  void  draw3DRect(int  x,  int  y,  int  width,  int  height,  boolean  raised)  :  주어진  크기와  모양(나오거나  들어간  모양)을  갖는  3D  사각형을  그린다.

■  public  abstract  void  drawArc(int  x,  int  y,  int  width,  int  height,  int  startAngle,  int  arcAngle)  :  주어진  크기의  사각형에  해당하는  호를  그리는데,  시작  각부터  주어진  각만큼의  크기를  갖는  호를  그린다.

■  public  void  drawBytes(byte[]  data,  int  offset,  int  length,  int  x,  int  y)  :  현재  폰트와  컬러를  이용하여  주어진  바이트  배열에  있는  문자열을  해당  위치에  그린다.

■  public  void  drawChars(char[]  data,  int  offset,  int  length,  int  x,  int  y)  :  현재  폰트와  컬러를  이용하여  주어진  문자  배열에  있는  문자열을  해당  위치에  그린다.

■  public  abstract  void  drawLine(int  x1,  int  y1,  int  x2,  int  y2)  :  (x1,  y1)에서  (x2,  y2)까지의  라인을  그린다.

■  public  abstract  void  drawOval(int  x,  int  y,  int  width,  int  height)  :  주어진  사각형에  맞는  타원을  그린다.

■  public  abstract  void  drawPolygon(int[]  xPoints,  int[]  yPoints,  int  nPoints)  :  주어진  좌표들을  꼭지점으로  하는  다각형을  그린다.

■  public  void  drawPolygon(Polygon  p)  :  주어진  좌표들을  꼭지점으로  하는  다각형을  그린다.

■  public  abstract  void  drawPolyline(int[]  xPoints,  int[]  yPoints,  int  nPoints)  :  주어진  좌표들을  연결하는  라인을  그린다.

■  public  void  drawRect(int  x,  int  y,  int  width,  int  height)  :  주어진  사각형을  그린다.

■  public  abstract  void  drawRoundRect(int  x,  int  y,  int  width,  int  height,  int  arcWidth,  int  arcHeight)  :  주어진  조건에  해당하는  둥근  사각형을  그리는데,  각의  너비와  높이에  맞게  둥글게  처리한다.

■  public  abstract  void  drawString(String  str,  int  x,  int  y)  :  현재  폰트와  컬러를  사용하여  주어진  문자열을  그린다.

■  public  void  fill3DRect(int  x,  int  y,  int  width,  int  height,  boolean  raised)  :  3D  사각형을  그려  현재  컬러로  채운다.

■  public  abstract  void  fillArc(int  x,  int  y,  int  width,  int  height,  int  startAngle,  int  arcAngle)  :  부채꼴  호를  그려  채운다.

■  public  abstract  void  fillOval(int  x,  int  y,  int  width,  int  height)  :  다원을  그려  채운다.

■  public  abstract  void  fillPolygon(int[]  xPoints,  int[]  yPoints,  int  nPoints)  :  다각형을  채운다.

■  public  void  fillPolygon(Polygon  p)  :  다각형을  채운다.

■  public  abstract  void  fillRect(int  x,  int  y,  int  width,  int  height)  :  사각형을  채운다.

■  public  abstract  void  fillRoundRect(int  x,  int  y,  int  width,  int  height,  int  arcWidth,  int  arcHeight)  :  둥근  사각형을  채운다.

■  public  abstract  Shape  getClip()  :  현재  클립  영역을  얻는다.

■  public  abstract  Rectangle  getClipBounds()  :  현재  클립  영역의  사각형  바운드를  얻는다.

■  public  Rectangle  getClipBounds(Rectangle  r)  :  현재  클립  영역의  사각형  바운드를  얻는다.

■  public  Rectangle  getClipRect()  :  getClipBounds()  메서드로  바뀌었다.

■  public  abstract  Color  getColor()  :  현재  컬러를  얻는다.

■  public  abstract  Font  getFont()  :  현재  폰트를  얻는다.

■  public  FontMetrics  getFontMetrics()  :  현재  폰트의  폰트  매트릭스를  얻는다.

■  public  abstract  FontMetrics  getFontMetrics(Font  f)  :  주어진  폰트에  대한폰트  매트릭스를  얻는다.

■  public  boolean  hitClip(int  x,  int  y,  int  width,  int  height)  :  주어진  사각형이  현재  클립  영역의  테두리와  겹치는  지를  얻는다.

■  public  abstract  void  setClip(int  x,  int  y,  int  width,  int  height)  :  주어진  사각형으로  현재  클립을  설정한다.

■  public  abstract  void  setClip(Shape  clip)  :  주어진  사각형으로  현재  클립을  설정한다.

■  public  abstract  void  setColor(Color  c)  :  주어진  컬러로  현재  컬러를  설정한다.

■  public  abstract  void  setFont(Font  font)  :  주어진  폰트로  현재  폰트를  설정한다.

■  public  abstract  void  setPaintMode()  :  현재  컬러로  페인트  모드를  설정한다.

■  public  abstract  void  setXORMode(Color  c1)  :  현재  컬러와  주어진  컬러를  이용하여  페인트  모드를  설정한다.


1.4.    MediaTracker  클래스  


“어,  못  들어본  클래스네!”  라고  생각하는  이들이  많을  것이다.  이  MediaTracker  클래스는  주로  네트워크  상  에서  많이  사용되는  클래스이다.  물론  네트워크와  관계없이  로컬  상에서도  사용된다.  하지만  이  MediaTracker  클래스의  기능을  알고  보면  왜  네트워크  상태에서  많이  사용하는지  알게  될  것이다.  이  MediaTracker  클래스는  로딩을  보장하기  위한  클래스이다.  쉽게  설명하면  그림이  전부  전송  될  때까지  기다리는  역할을  한다.  그럼  예제를  보자.

다음은  MediaTracker  클래스는  이용해  이미지를  로딩하는  예제이다.


MediaTrackerTest.java(MediaTracker  클래스는  테스트하기  위한  예제)

import  java.awt.*;

import  java.awt.image.*;

public  class  MediaTrackerTest  extends  Frame  {

      private  Image  image=null;

      private  BufferedImage  bi  =  null;

      private  int  width  =0;

      private  int  height  =0;

      public  static  void  main(String  args[])  {

              MediaTrackerTest  mtt  =  new  MediaTrackerTest();

              mtt.makeImage("java_logo.jpg");

      }

      public  MediaTrackerTest()  {

              this.setSize(150,170);

              this.show();

      }                                                        

      public  void  makeImage(String  filename)  {

              try  {

                    image  =  Toolkit.getDefaultToolkit().getImage(filename);

                MediaTracker  tracker  =  new  MediaTracker(this);

                tracker.addImage(image,0);

                tracker.waitForID(0);

                  width=  image.getWidth(null);

                    height=  image.getHeight(null);

                    bi  =  new  BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

                    Graphics  gg  =  bi.getGraphics();              

                    gg.drawImage(image,  0,0,  this);

                    gg.dispose();

                    repaint();

              }  catch  (Exception  ex){

                    System.out.println(ex.toString());

              }

      }

      public  void  paint  (Graphics  g)  {

              if(bi!=null)

                    g.drawImage(bi,  50,50,  this);

      }

}


C:\JavaExample\14>javac  JPEGFileEncodeImage.java

C:\JavaExample\14>java  JPEGFileEncodeImage

  


MediaTracker  클래스는  설명하기  위해  예제를  냈는데,  다른  부분이  훨씬  더  많다.  예제의  자세한  부분은  뒤에  이미지  로딩  부분에서  설명  드리고  지금은  원래대로  MediaTracker  클래스에  대해서  설명한다.

MediaTracker  클래스는  10장에서  배웠던  Object  클래스의  wait()  메서드와  비슷하다.  눈치  빠른  분들은  이해했을  것이다.

예제에서  보면  MediaTracker  클래스는  사용하기  바로  아래  구문에서  이미지를  로드하고  있다.  먼저  Image클래스의  객체  image를  생성했다.

Image  image  =  Toolkit.getDefaultToolkit().getImage(filename);


java.awt.Toolkit  클래스의  멤버  메서드인  getDefaultToolkit()  메서드와  getImage(String  filename)  메서드를  사용하여  image  객체를  얻어오고  있다.  이  때  MediaTracker  클래스를  사용한다.

MediaTracker  tracker  =  new  MediaTracker(this);


우  선  MediaTracker  클래스의  객체  tracker를  생성했다.  근데  여기에서  전에  보던  놈이  나왔다.  this라는  것이  갑자기  튀어  나왔다.  우리는  이  this에  대하여  4장에서  배웠다.  기억이  안  나면  4장을  확인  해  보자.  ‘언젠가  생길  내  주소의  this’  생각이  나나?  그래도  아리송하나?  MediaTracker  클래스의  생성자  메서드는  객체를  생성할  때  이미지를  그릴  컴포넌트를  요구한다.  그런데  위의  예제에서  이미지를  그릴  컴포넌트는  Frame이다.  하지만  지금  프로그램을  디자인하고  있어,  메모리가  생성도  되지  않았는데  어떻게  참조값을  넘겨  줄  수  있겠나?  그래서  여기에서  this를  사용해서  지금은  참조값이  없지만  프로그램이  실행되어  Frame이  생성되면  그  Frame의  메모리  주소를  넘겨주겠다는  뜻이다.  별로  어려울  것이  없다.

tracker.addImage(image,  0);

tracker.waitForID(0);


그  리고  생성한  객체  tracker를  이용하여  addImage(Image  image,  int  id)  메서드를  호출하였다.  이  메서드는  tracker  객체가  어떤  이미지를  목표로  삼을지를  알려주고,  그  이미지에  id값을  준다.  그리고  tracker  객체는  waitForID(int  id)  메서드를  호출하여  준다.  이  메서드는  입력된  id값을  가지고  있는  image가  전부  로딩이  될  때까지  프로그램을  wait시킨다.  그런  후  image가  전부  로딩되면  자동으로  notify  해주는  것이다.  이제  왜  네트워크  상에서  많이  사용하는지  이유를  알  것  같지  않나?  만약  온라인  상에서  그림이  전부  넘어오지도  않았는데  프로그램이  계속  진행된다면  어떻게  될까?  바로  그런  것을  방지해주는  것이다.  만약  이미지로드  또는  배율조정  중에  오류가  발생하면  그  이미지의  로드는  완료된  것으로  간주한다.  그럴  때  isErrorAny()  메서드와  isErrorID()  메서드를  사용해서  오류를  점검하면  된다.

그  런데  이렇게  길게  설명했는데  예제의  굵은  글씨로  표시된  부분을  빼고  컴파일하여도  에러는  나타나지  않는다.  하지만  결과가  똑같이  나온다고  보장은  할  수  없다.  똑같이  나오는  예제도  있고,  그렇지  않은  예제도  있다.  위의  예제는  안  해주면  에러가  뜨는  예제이다.  실행  시의  에러  발생이다.  만약  사용하지  않아도  되는  예제는  사용자가  결정하면  된다.  하지만  사용하는  것이  안전하다.

왜  MediaTracker  클래스는  네트워크  상에서  많이  사용한다는  것을  이제  좀  이해하리라  믿는다.  “일종의  wait()  메서드다.”라고  생각하면  그다지  어려울  것도  없는  놈이다.  하지만  꼭  사용하라는  것은  아니니  잘  생각하여  프로그램을  작성하자.  그리고  이  MediaTracker  클래스는  이미지뿐만  아니라  오디오를  지원하게  만든다고  했지만  아직  지원하지  않는다.


MediaTracker

■  MediaTracker  tracker  =  new  MediaTracker(this);

addImage(Image  image,  int  id)  :  메서드를  사용해서  추적해야  할  이미지를  설정하고,  id값을  설정한다.

waitForID(int  id)  :  메서드를  사용해서  입력된  id값의  image가  로딩  될  때까지  프로그램을  wait시킨다.


MediaTracker  생성자  메서드

■  public  MediaTracker(Component  comp)  :  지정된  컴포넌트의  이미지를  추적하는  MediaTracker  객체를  작성한다.


MediaTracker  주요  멤버  메서드

■  public  void  addImage(Image  image,  int  id)  :  매체  추적자가  추적  중인  이미지의  목록에  이미지를  추가한다.

■  public  void  addImage(Image  image,  int  id  ,  int  w,  int  h)  :  매체  추적자가  추적  중인  이미지의  목록에  배율을  조정한  이미지를  추가한다.

■  public  boolean  checkAll()  :  매체  추적자가  추적  중인  이미지를  모두  로드했는  지  여부를  점검한다.

■  public  boolean  checkAll(boolean  load)  :  매체  추적자가  추적  중인  이미지를  모두  로드했는  지  여부를  점검한다.

■  public  boolean  checkID(int  id)  :  매체  추적자가  추적하는  지정된  식별자를  가진  이미지를  모두  로드했는  지  여부를  점검한다.

■  public  boolean  checkID(int  id,  boolean  load)  :  매체  추적자가  추적하는  지정된  식별자를  가진  이미지를  모두  로드했는  지  여부를  점검한다.

■  public  Object[]  getErrorsAny()  :  오류가  발생한  모든  매체  목록을  리턴한다.

■  public  Object[]  getErrorsID(int  id)  :  지정된  ID를  가졌으며  오류가  발생한  매체  목록을  리턴한다.

■  public  boolean  isErrorAny()  :  모든  이미지의  오류  상태를  점검한다.

■  public  boolean  isErrorID(int  id)  :  매체  추적자가  추적하는  지정된  식별자를  가진  모든  이미지의  오류  상태를  점검한다.

■  public  void  removeImage(Image  image)  :  매체  추적자에서  지정된  이미지를  제거한다.

■  public  void  removeImage(Image  image,  int  id)  :  매체  추적자의  지정된  추적  ID에서  지정된  이미지를  제거한다.

■  public  void  removeImage(Image  image,  int  id,  int  w,  int  h)  :  매체  추적자에서  지정된  가로  길이,  세로  길이  및  ID를  가진  지정된  이미지를  제거한다.

■  public  int  statusAll(boolean  load)  :  매체  추적자가  추적하는  모든  매체  상태의  bitwise  inclusive  OR을  계산하고  리턴한다.

■  public  int  statusID(int  id,  boolean  load)  :  매체  추적자가  추적하는  지정된  식별자는  가진  모든  매체  상태의  bitwise  inclusive  OR을  계산하고  리턴한다.

■  public  void  waitForAll()  :  매체  추적자가  추적하는  모든  이미지의  로드를  시작한다.

■  public  boolean  waitForAll(long  ms)  :  매체  추적자가  추적하는  모든  이미지의  로드를  시작한다.

■  public  void  waitForID(int  id)  :  매체  추적자가  추적하는  지정된  식별자를  가진  모든  이미지  로드를  시작한다.

■  public  boolean  waitForID(int  id,  long  ms)  :  매체  추적자가  추적하는  지정된  식별자는  가진  모든  이미지  로드를  시작한다.


1.5.    2D  Graphics


자  바  2D  Graphics는  2D에서  알  수  있듯이  자바의  Graphics  클래스의  메서드들을  이용해서  구현했던  여러  가지  도형들이나  선,  그리고  글씨들까지도  2차원으로  표현한  것이다.  2차원을  구현했기  때문에  그려지는  것들이  동적이며  매우  화려하다.  이  2D  Graphics를  지원해  주는  클래스가  Graphics2d  클래스이다.  클래스의  멤버  메서드들을  잠깐  봐도  Graphics와  많이  비슷하다.  왜냐하면  Graphics2d  클래스는  Graphics를  상속받았기  때문이다.  쉽게  Graphics보다  좀  더  화려해지고,  동적으로  변했다라고  생각하면  될  것  같다.

Graphics2D를  제대로  구현하려면  java.awt.geom  패키지  등  여러  패키지를  import시켜야  한다.  하여간  먼저  예제를  보자.


Graphics2DTest.html  (Applet을  로딩하기  위한  html파일)

<applet  code="Graphics2DTest"  width=400  height=300>

</applet>



Graphics2DTest.java  (2D  Graphics를  테스트하기  위한예제)

import  java.applet.*;

import  java.awt.*;

import  java.awt.event.*;

import  java.awt.font.TextLayout;

import  java.awt.font.TextHitInfo;

import  java.awt.font.FontRenderContext;

import  java.awt.geom.Rectangle2D;

import  java.awt.geom.AffineTransform;

import  java.awt.image.BufferedImage;

public  class  Graphics2DTest  extends  Applet  implements  Runnable  {

        private  static  String  text[]  =  {  "www.jabook.org",  "Graphics2D"  };

        private  static  Color  colors[]  =  {  Color.cyan,  Color.lightGray  };

        private  static  Font  smallF  =  new  Font("Georgia",  Font.PLAIN,  8);

        private  int[]  curPos;

        private  TextLayout[]  layouts;

        private  Font[]  fonts;

        private  long  sleepAmount  =  900;

        private  Thread  thread;

        private  BufferedImage  bimg;

        public  void  init()  {

                  final  Graphics2DTest  g2d  =  new  Graphics2DTest();

                  setBackground(Color.white);

              fonts  =  new  Font[2];

              layouts  =  new  TextLayout[fonts.length];

              curPos  =  new  int[fonts.length];

        }

        public  void  reset(int  w,  int  h)  {

                fonts[0]  =  new  Font("Georgia",Font.PLAIN,w/text[0].length()+8);

                fonts[1]  =  new  Font("serif",  Font.BOLD,w/text[1].length());

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

                        curPos[i]  =  0;

                }

        }

        public  void  step(int  w,  int  h)  {

                for  (int  i  =  0;  i  <  2;  i++)  {

                        if  (layouts[i]  ==  null)  {

                                continue;

                        }

                        if  (curPos[i]++  ==  layouts[i].getCharacterCount())  {

                                curPos[i]  =  0;

                        }

                }

        }

        public  void  drawg2d(int  w,  int  h,  Graphics2D  g2)  {

                FontRenderContext  frc  =  g2.getFontRenderContext();

                for  (int  i  =  0;  i  <  2;  i++)  {

                        layouts[i]    =  new  TextLayout(text[i],  fonts[i],  frc);

                        float  rx  =  (float)  (w/2-layouts[i].getBounds().getWidth()/2);

                        float  ry  =  (float)  ((i  ==  0)  ?  h/3  :  h  *  0.75f);

                        float  rw  =  (float)  (layouts[i].getBounds().getWidth());

                        float  rh  =  (float)  (layouts[i].getBounds().getHeight());

                        Shape  hilite  =  layouts[i].getLogicalHighlightShape(0,  curPos[i]);

                        AffineTransform  at  =  AffineTransform.getTranslateInstance(rx,  ry);

                        hilite  =  at.createTransformedShape(hilite);

                        float  hy  =  (float)  hilite.getBounds().getY();

                        float  hh  =  (float)  hilite.getBounds().getHeight();

                        g2.setColor(colors[i]);

                        g2.fill(hilite);

                        Shape[]  shapes  =  layouts[i].getCaretShapes(curPos[i]);

                        Shape  caret  =  at.createTransformedShape(shapes[0]);

                        g2.setColor(Color.black);

                        layouts[i].draw(g2,  rx,  ry);

                        g2.draw(caret);

                        g2.draw(new  Rectangle2D.Float(rx,hy,rw,hh));

                        for  (int  j  =  0;  j  <=  layouts[i].getCharacterCount();  j++)  {

                                float[]  cInfo  =  layouts[i].getCaretInfo(TextHitInfo.leading(j));

                                String  str  =  String.valueOf((int)  cInfo[0]);

                                TextLayout  tl  =  new  TextLayout(str,smallF,frc);

                                tl.draw(g2,  (float)  rx+cInfo[0],  hy+hh+tl.getAscent()+1.0f);

                        }

                }

        }

        public  Graphics2D  createGraphics2D(int  w,  int  h)  {

                Graphics2D  g2  =  null;

                if  (bimg  ==  null  ||  bimg.getWidth()  !=  w  ||  bimg.getHeight()  !=  h)  {

                        bimg  =  (BufferedImage)  createImage(w,  h);

                        reset(w,  h);

                }

                g2  =  bimg.createGraphics();

                g2.setBackground(getBackground());

                g2.clearRect(0,  0,  w,  h);

                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,  RenderingHints.VALUE_ANTIALIAS_ON);

                return  g2;

        }

        public  void  start()  {

                thread  =  new  Thread(this);

                thread.setPriority(Thread.MIN_PRIORITY);

                thread.start();

        }

      public  void  paint(Graphics  g)  {

          Dimension  d  =  getSize();

                step(d.width,  d.height);

                Graphics2D  g2  =  createGraphics2D(d.width,  d.height);

                drawg2d(d.width,  d.height,  g2);

                g2.dispose();

                g.drawImage(bimg,  0,  0,  this);

        }

        public  Synchronized  void  stop()  {

                thread  =  null;

        }

        public  void  run()  {

                try  {

                        thread.sleep(1000);

                }  catch  (InterruptedException  e)  {  return;  }

                Thread  me  =  Thread.currentThread();

                while  (thread  ==  me)  {

                        repaint();

                        try  {

                                thread.sleep(sleepAmount);

                        }  catch  (InterruptedException  e)  {  break;  }

                }

                thread  =  null;

        }

}

C:\JavaExample\14>javac  Graphics2DTest.java

C:\JavaExample\14>appletviewer  Graphics2DTest.html


  


조  금  긴  것  같은  예제였지만  별로  길지는  않다?  이  예제는  실행해  보면  알겠지만  글씨가  써진  블록  부분이  조금씩  색으로  채워지는  Applet이  나타난다.  Applet은  다음  장에서  자세히  설명하겠다.  앞에서  13장  AWT에서  보아왔던  것과는  조금  다르다고  느낄  것이다.  위의  두  개의  파일은  따로  저장해야  한다.  Applet은  html로  시작한다.  그  것이  특이한  점  중  하나이다.  예제를  보면  알겠지만  main()  메서드가  없다.  대신에  html이  로딩을  시켜주며  처음  시작은  init()  메서드부터  시작한다.

2D  Graphics는  java.awt.geom  패키지에  있는  클래스들로  여러  가지  형태의  도형(곡선,  호,  선  등)들을  그릴  수  있다.  그리고  그  도형을  Graphics2d  클래스의  객체를  사용하여  도형의  기능들을  더욱  강력하게  만들어  준다.  먼저  java.awt.geom  패키지를  import시켜야  한다.

import  java.awt.geom.Rectangle2D;

import  java.awt.geom.AffineTransform;


여  기에서는  직접  클래스를  import시켰다.  Rectangle2D  클래스는,  위치(x,  y)및  사이즈(width  X  height)로  정의되는  사각형을  기술한다.  AffineTransform  클래스는  측도  변환을  비롯해  좌표계의  이동  및  회전을  모두  포함하는  좌표변환을  하는  클래스이다.  사용자  공간에서  디바이스  공간으로  도형을  옮겨  표현할  때,  affine  transform적용된다.  사용자  공간(User  Space)이란  프로그래머  혹은  프로그램에서  사용하는  디바이스  독립한  좌표공간을  말하며,  디바이스  공간(Device  Space)이란  출력  장치가  사용하는  좌표  공간이다.  어려워지나?

또  다른  패키지의  클래스를  import시켰다.

import  java.awt.font.TextLayout;

import  java.awt.font.TextHitInfo;

import  java.awt.font.FontRenderContext;


TextLayout  클래스는  여러  가지  기능이  있다만  여기에서는  커서의  위치  지정과  이동  기능을  하는  역할을  한다.  TextHitInfo  클래스는  텍스트  모델내의  문자의  위치  및  그  문자의  bias  or  side를  나타낸다.  bias는,  leading(왼쪽에서  오른쪽으로  기술하는  문자의  왼쪽  끝)  또는  trailing(왼쪽에서  오른쪽으로  기술하는  문자의  오른쪽  끝)의  어느  쪽인가  이다.  TextHitInfo  클래스의  객체는  텍스트내의  글자  및  삽입  위치를  지정하기  위해서  사용된다.  FontRenderContext  클래스는  텍스트의  size를  올바르게  측정하는데  필요한  정보의  컨테이너이다.  텍스트의  size는  아우트라인을  픽셀에  표시하는  규칙이나,  어플리케이션이  제공하는  표현  힌트에  의해  바뀌는  경우가  있다.  그렇지만  위의  클래스가  설명한  기능만  하는  것이  아님을  알아야  한다.

public  class  Graphics2DTest  extends  Applet  implements  Runnable  {  }


예  제가  Applet을  상속받았다.  그리고  Runnable  인터페이스를  implements하였다.  여기서는  특이하게  final로  지정하고  있는  데  그  이유는  시간의  흐름에  따라  스레드바가  변하는데  변하는  동안  스레드바를  제외한  텍스트들과  TextLayout,  Font,  스레드바의  Color  등이  변하지  않게  하기  위해서  이다.

위에서  Applet은  html로  시작한다고  말했다.  그리고  시작은  init()  메서드부터  이다.

public  void  init()  {  }


이  제  init()  메서드부터  시작해  볼까?  참,  Applet은  주기라는  것이  있다.  init()  →  start()  →  paint()  →  stop()  →  destroy()  이렇게  자동으로  실행이  된다.  편리한  놈이다.  init()  메서드  안에서  객체를  생성시켰다.

public  void  init()  {

      final  Graphics2DTest  g2d  =  new  Graphics2DTest();

      setBackground(Color.white);

      fonts  =  new  Font[2];

      layouts  =  new  TextLayout[fonts.length];

      curPos  =  new  int[fonts.length];

}


여기에서  생성된  3개의  객체에서  fonts는  두  개의  폰트  배열을  나타내고,  layout은  폰트  배열의  개수만큼  TextLayout  배열을  나타내며,  curPos는  폰트  배열의  개수만큼의  int형  배열이다.

init()  메서드는  자동으로  start()  메서드를  호출한다.  호출된  start()  메서드에서  thread를  생성하고,  이  thread를  start시켰다.

public  void  start()  {

      thread  =  new  Thread(this);

      thread.setPriority(Thread.MIN_PRIORITY);

      thread.start();

}


여  기에서  처음에  실행된  메서드는  Applet의  start()  메서드이고,  그  안에서  호출된  start()  메서드는  Thread의  start()  메서드이다.  Thread의  start()  메서드는  run()  메서드를  호출한다.  알고  있을  것이다?

public  void  run()  {

      try  {

            thread.sleep(1000);

      }  catch  (InterruptedException  e)  {  return;  }

      Thread  me  =  Thread.currentThread();

      while  (thread  ==  me)  {

            repaint();

            try  {

                  thread.sleep(sleepAmount);

            }  catch  (InterruptedException  e)  {  break;  }

      }

      thread  =  null;

}


여기에서  thread의  정지시간을  1000ms(1초)으로  주고  현재  실행중인  thread가  자기의  것이라면  repaint  해  준다.  그리고  정해준  시간만큼  또  정지하게  된다.

위에서  Applet의  start()  메서드를  호출하였는데,  이  메서드는  paint(Graphics  g)  메서드를  호출하게  된다.

public  void  paint(Graphics  g)  {

      Dimension  d  =  getSize();

      step(d.width,  d.height);

      Graphics2D  g2  =  createGraphics2D(d.width,  d.height);

      drawg2d(d.width,  d.height,  g2);

      g2.dispose();

      g.drawImage(bimg,  0,  0,  this);

}


이  paint(Graphics  g)  메서드가  가장  핵심적인  부분이다.  먼저  getSize()  메서드를  사용하여  Dimension  클래스의  객체  d를  만들었다.  그리고  d.width와  d.height를  매개변수로  사용하여  step()  메서드를  호출하였다.  그리고  createGraphics2D(d.width,  d.height)  메서드를  사용하여  Graphics2d  클래스의  객체  g2를  생성하였다.

public  Graphics2D  createGraphics2D(int  w,  int  h)  {

      Graphics2D  g2  =  null;

      if  (bimg  ==  null  ||  bimg.getWidth()  !=  w  ||  bimg.getHeight()  !=  h)  {

            bimg  =  (BufferedImage)  createImage(w,  h);

            reset(w,  h);

      }

      g2  =  bimg.createGraphics();

      g2.setBackground(getBackground());

      g2.clearRect(0,  0,  w,  h);

      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,    RenderingHints.VALUE_ANTIALIAS_ON);

      return  g2;

}


이  메서드  속을  들여다보자.  먼저  if문을  사용하여  BufferedImage  클래스의  bimg  객체가  null  값을  갖거나,  이미지의  크기가  다르다면  reset(w,  h)  메서드를  사용해서  폰트  배열  객체를  생성하고  있다.  BufferedImage  클래스의  멤버  메서드인  createGraphics()를  사용하여  Graphics2d  클래스의  객체  g2를  생성하였다.  이렇게  생성된  Graphics2d  클래스의  g2로  setBackground(getBackground())  메서드를  사용하여  Graphics2D  문맥의  백그라운드  칼라를  설정한다.  백그라운드  칼라는,  영역을  clear하기  위해서  사용된다.  그  후  clearRect()  메서드를  사용하여  영역을  clear하였다.  그리고  setRenderingHint()  메서드를  사용하여  표현  알고리즘의  추천  설정의  값을  1개  설정하였죠.  그  후  객체  g2를  리턴시켰다.

다시  paint()  메서드로  돌아와서  d.width,  d.height,  그리고  g2를  매개변수로  써서  drawg2d()  메서드를  호출하였다.

public  void  drawg2d(int  w,  int  h,  Graphics2D  g2)  {  }


그  리고  g2.getFontRenderContext()  메서드를  사용하여  FontRenderContext  클래스의  객체  frc를  생성하였다.  getFontRenderContext()  메서드는  Graphics2d  클래스  문맥에서의  Font의  표현  문맥을  리턴  한다.  말이  좀  어렵다.  그냥  표현해야  하는  정보를  반환하는  정도로  생각하셔도  무방할  듯  싶다.  그리고  for문을  사용하여  여러  가지  값들과  메서드들을  호출하였다.

FontRenderContext  frc  =  g2.getFontRenderContext();

for  (int  i  =  0;  i  <  2;  i++)  {

      //  여러  가지  값과  메서드들이  들어간다.

  }


먼저  layouts  객체배열을  구했다.  TextLayout  클래스의  생성자  메서드를  이용하여  값을  결정하였다.  그리고  다른  메서드들의  매개변수의  값들을  구했다.

      layouts[i]  =  new  TextLayout(text[i],  fonts[i],  frc);

      float  rx  =  (float)  (w/2-layouts[i].getBounds().getWidth()/2);

      float  ry  =  (float)  ((i  ==  0)  ?  h/3  :  h  *  0.75f);

      float  rw  =  (float)  (layouts[i].getBounds().getWidth());

      float  rh  =  (float)  (layouts[i].getBounds().getHeight());


계  속해서  getLogicalHighlightShape(int  firstEndpoint,  int  secondEndpoint)  메서드를  사용해서  지정된  범위의  논리적인  선택  범위를  둘러싸는  Shape를,  이  TextLayout의  자연  경계까지  확장해  돌려준다.  그리고  AffineTransform클래스의  TranslateInstance(double  tx,  double  ty)  메서드를  사용하여  평행이동  변환을  표현하는  변환을  얻어내고,  createTransformedShape(Shape  pSrc)  메서드를  사용하여  지정된  Shape를  이  변환에  의해  변환해,  그  Shape의  구조에  의해  정의  되는  새로운  Shape클래스의  객체를  돌려준다.

      Shape  hilite  =  layouts[i].getLogicalHighlightShape(0,  curPos[i]);

      AffineTransform  at  =  AffineTransform.getTranslateInstance(rx,  ry);

      hilite  =  at.createTransformedShape(hilite);


또  여기서,  메서드에  사용될  매개변수를  구했다.  getBound()  메서드는  Shape를  완전하게  둘러싸는  정수의  Rectangle을  반환한다

      float  hy  =  (float)  hilite.getBounds().getY();

      float  hh  =  (float)  hilite.getBounds().getHeight();


그  다음  색을  설정하고,  그  도형의  내부를  색칠을  한다.  그리고  문자와  Rectangle을  그려준다.

      g2.setColor(colors[i]);

      g2.fill(hilite);

      Shape[]  shapes  =  layouts[i].getCaretShapes(curPos[i]);

      Shape  caret  =  at.createTransformedShape(shapes[0]);

      g2.setColor(Color.black);

      layouts[i].draw(g2,  rx,  ry);

      g2.draw(caret);

      g2.draw(new  Rectangle2D.Float(rx,hy,rw,hh));


이렇게  paint(Graphics  g)  메서드를  설명하였다.  정말  길다.  Thread가  repaint()  메서드를  호출하면  다시  paint(Graphics  g)  메서드를  실행시켜주면  된다.

상  당히  어려운  예제였다.  하지만  천천히  다시  살펴보면  처음보다는  쉽다.  Graphics2d  클래스는  Graphics  클래스를  상속  받아  생성된  클래스이다.  그래서  Graphics  클래스의  모든  멤버  메서드를  사용할  수  있다.  거기에  자기의  메서드들이  더해지고  java.awt.geom  패키지나  java.awt.font  패키지의  라이브러리를  사용하여  강력한  기능을  나타내고  있다.  메서드들의  반환형들이  생소한  타입들이  많이  나오는  편이다.  그래서  많이들  어려워한다.    하지만  사용만  할  수  있다면  더욱  멋진  Graphic을  사용할  수  있다.