그래픽.1 스윙 컴포넌트 그리기.4 이미지 그리기.2 Graphics.5 repaint()와 그래픽 응용.3 도형 그리기와 칠하기
그래픽 chapter.1 스윙컴포넌트그리기 컴포넌트는자신의모양을스스로그린다 X-window, MFC, C# GUI, Android 등 GUI 플랫폼에서 GUI 컴포넌트는스스로자신의모양을그린다. 자바의스윙도예외는아니다. JButton은버튼모양을그리는코드를내장하고, JComboBox 역시콤보박스를그리는코드를가지고있다. 컨테이너가이들을대신그려주지않으며, 자바가상기계가하지도않는다. 개발자가새로운컴포넌트를설계하여구현하고자한다면, 컴포넌트의모양을그리는코드를컴포넌트안에작성하여야할것이다. 자바의스윙은컴포넌트들이자신의모양을그리는코드를 paintcomponent() 라는메소드에작성하도록설계하였다. 지금부터 paintcomponent() 에대해자세히알아보자. paintcomponent() paintcomponent() 스윙컴포넌트가자신의모양을그리는 paintcomponent() 메소드의원형은다음과같다. public void paintcomponent(graphics g) paintcomponent() 는 JComponent의추상메소드로서, 모든스윙컴포넌트가오버라이딩하여가지고있다. 예를들어 JButton의 paintcomponent() 는텍스트나이미지로구성된버튼을그리고, JTextField의 paintcomponent() 는입력창을그리며, JRadioButton의 paintcomponent() 는텍스트와동그란라디오버튼을그린다. paintcomponent() 는자바플랫폼에의해호출되며, 개발자가직접호출해서는안된다. 그러면 paintcomponent() 가호출되는경우는언제일까? 간단히말하면컴포넌트가화면에그려져야하는경우로서, 다음 5가지경우이다.
그래픽 CHAPTER 435 컴포넌트가처음으로그려질때 컴포넌트의크기나위치변경등컴포넌트에변화가생길때 다른윈도우에의해가려졌다가드러날때 아이콘화되었다가본래크기로복구할때 프로그램이컴포넌트의 repaint() 메소드를호출할때 paintcomponent(graphics g) 에인자로넘어오는 Graphics 객체 g를그래픽컨텍스트 (graphics context) 라고부르며자바플랫폼에의해생성되어공급된다. 화실에서그림을그리려면, 캔버스와붓, 연필, 물감, 지우개등다양한도구가필요한것처럼, 자바플랫폼은컴포넌트그리기를위한다양한메소드와필드를 Graphics 객체를통해제공한다. 개발자는오직 Graphics 객체만을이용하여그려야만한다. Graphics 는뒤에서자세히설명한다. Graphics paintcomponent() 의오버라이딩 개발자가 JComponent를상속받아새로운컴포넌트를설계하든지아니면기존의스윙컴포넌트모양에변화를주고자할때, 다음과같이 paintcomponent() 를오버라이딩하여자신만의컴포넌트모양을그릴수있다. class MyComponent extends JXXX { // JXXX는기존의스윙컴포넌트...... 컴포넌트를그리는코드작성...... paintcomponent() 를오버라이딩하면원하는모양을그릴수있어.
436 자바에센셜 JAVA JPanel 에그리기 JPanel JPanel 은빈캔버스와같이아무모양도없는텅빈컴포넌트이면서컨테이너이다. JPanel은개발자가그래픽을통해다양한 GUI를창출할수있는캔버스로적합하기때문에그래픽을위해많이사용된다. JPanel에그리기를수행하는예를살펴보자. 아래와같이 JPanel 클래스를상속받고 paintcomponent() 를오버라이딩하여이곳에그리기를구현한다. // JPanel에구현된 paintcomponent() 호출 g.setcolor(color.blue); // 파란색선택. 이후그리기는파란색으로진행 g.drawrect(10,10,50,50); // (10,10) 위치에 50 50 크기의사각형그리기 g.drawrect(50,50,50,50); // (50,50) 위치에 50 50 크기의사각형그리기 g.drawrect(90,90,50,50); // (90,90) 위치에 50 50 크기의사각형그리기 이코드를잠깐살펴보자. 다음라인은 paintcomponent(graphics g) 의인자로넘어오는 Graphics 객체 g에파란색을지정한다. g.setcolor(color.blue); // 파란색선택 지금부터모든그리기, 칠하기, 문자출력등그래픽처리에파란색이이용된다. Graphics 클래스의 drawrect() 메소드는사각형을그리는것으로, 다음코드는 JPanel 상의 (10,10) 위치에 50 50 크기의파란색사각형을그린다. g.drawrect(10,10,50,50); // (10,10) 위치에 50 50 크기의사각형그리기 JPanel에구현되어있는 paintcomponent() 는패널에그려진이전내용을모두지우고, setbackground() 에의해설정된배경색으로패널의바탕을칠하도록구현되어있다. 그러므로 MyPanel의 paintcomponent() 에서다음을호출하면, // JPanel 에구현된 paintcomponent() 호출 super.paintcomponent() 이전에그려진내용을모두지울수있다. 일반적으로 JPanel을상속받아 paintcomponent() 를작성하는경우 super.paintcomponent() 를제일먼저호출하는것이좋다. JPanel뿐아니라다른스윙컴포넌트를상속받는경우도마찬가지이다. 지금까지설명한내용을예제 -1로구성하였다.
그래픽 CHAPTER 437 JPanel 을상속받은패널에도형그리기 예제 -1 JPanel 을상속받아패널을구성하고이곳에그림과같은 3 개의도형을그려라. (10,10) 50 50 크기 (50,50) (90,90) 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import javax.swing.*; import java.awt.*; public class paintjpanelex extends JFrame { paintjpanelex() { settitle("jpanel의 paintcomponent() 예제 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); // 생성한패널을컨텐트팬으로사용 setsize(250,200); setvisible(true); // JPanel을상속받는새패널구현 MyPanel의내부를그리는메소드로서 3개의사각형을그린다. // JPanel의 paintcomponent() 호출패널내에이전에그려진잔상을지우기위해호출한다. g.setcolor(color.blue); // 파란색선택 g.drawrect(10,10,50,50); // (10,10) 위치에 50x50 크기의사각형그리기 g.drawrect(50,50,50,50); // (50,50) 위치에 50x50 크기의사각형그리기 g.setcolor(color.magenta); // 마젠타색선택 g.drawrect(90,90,50,50); // (90,90) 위치에 50x50 크기의사각형그리기 public static void main(string [] args) { new paintjpanelex();
438 자바에센셜 JAVA.2 Graphics 10 장에서는컴포넌트를기반으로 GUI 프로그램을작성하는방법에대해설명하였다. 이장에서는그래픽기반으로 GUI 프로그램을작성하는방법에대해소개한다. 그래픽기반 GUI 프로그래밍 그래픽 그래픽이란개발자가스윙컴포넌트에의존하지않고선, 원, 이미지등을이용하여직접화면을구성하는기능을말한다. 그러면그래픽이필요한이유는무엇일까? 첫째, 스윙컴포넌트는사용하기쉽고전형적인모양의사용자인터페이스를만들기에는효과적이지만, 차트. 게임화면등자유로운콘텐트를표현하기에는부족함이있다. 도형그리기, 이미지그리기등그래픽을이용하면, 기존의스윙컴포넌트로만들어내지못하는모양을자유자재로만들어낼수있다. 둘째, 그래픽기능을이용하는경우화면의출력속도가매우빠르다. 스윙컴포넌트는그려지는데상대적으로많은시간이걸리므로, 화면이역동적으로변하고속도가중요한게임등의경우, 스윙컴포넌트로는화면갱신속도를맞추는데문제가있을수있다. 셋째, 스윙은기본적으로그래픽기능을이용하여작성되었기때문에, 자바의 GUI 바탕기술을이해하는데도움이된다. 넷째, 개발자는그래픽을이용하여자신만의컴포넌트를개발할수있다. Graphics Graphics Graphics 클래스의경로명은 java.awt.graphics이며, 자바의초기부터 AWT와함께제공된기능으로, 그리기, 칠하기, 이미지출력, 클리핑등 GUI 프로그래밍에있어필요한필드와메소드를제공한다. Graphics의좌표체계자바그래픽의좌표값은그래픽대상컴포넌트의왼쪽상단모서리가 (0, 0) 이고, 오른쪽으로 X축값이증가하며, 아래쪽으로 Y축값이증가한다. (0,0) X 축 Y 축 [ 그림 -1] 자바의그래픽좌표체계
그래픽 CHAPTER 439 Graphics의기능 Graphics가제공하는기능은간단히다음과같다. 색상선택하기 문자열그리기 도형그리기 도형칠하기 이미지그리기 클리핑 문자열그리기 문자열그리기를위한 Graphics 메소드는다음과같다. void drawstring(string str, int x, int y) str 문자열을 (x,y) 영역에그림. 현재 Graphics 에설정된색과폰트로문자열출력 drawstring() 을사용하여 (30, 30) 위치에서 " 자바는재밌다.~~" 를출력하는예를 들면다음과같다. drawstring() Graphics g; g.drawstring(" 자바는재밌다.~~", 30,30); 문자가출력되는 (30,30) 의위치는예제 -2 에서확인하기바란다. 색상과폰트, Color 와 Font Color 와 Font 클래스는색과문자폰트를지정하는데사용된다. Color Color는색을표현하는클래스이다. 자바에서색은 r(red), g(green), b(blue) 성분으로구성되며, 각성분은 0~255(8비트 ) 범위의정수이다. Color의생성자는다음과같다. Color Color(int r, int g, int b) r, g, b 값으로 srgb 색생성 Color(int rgb) rgb는 32비트의정수이지만하위 24비트만유효. 즉, 0x00rrggbb로표현. 각바이트가 r, g, b의색성분
440 자바에센셜 JAVA 색은생성자를이용하지않고간단히 Color 클래스에상수로선언된 Color.BLUE, Color.YELLOW 등을사용할수도있다. Color 클래스를사용하는예를들어보자. Graphics g; g.setcolor(new Color(255, 0, 0)); // 빨간색을생성하여그래픽색으로지정한다. g.setcolor(new Color(0x0000ff00)); // 초록색을생성하여그래픽색으로지정한다. g.setcolor(color.yellow); // 노란색을그래픽색으로지정한다. Font Font Font 는문자의폰트정보를담으며, 생성자는다음과같다. Font(String fontface, int style, int size) fontface: " 고딕체 ", "Ariel" 등과같은폰트이름 style: Font.BOLD, Font.ITALIC, Font.PLAIN 중한값으로문자의스타일 size: 픽셀단위의문자크기 예를들어, 이탤릭스타일을가진 "Times New Roman" 체의 30픽셀폰트를생성하면다음과같다. Font f = new Font("Times New Roman", Font.ITALIC, 30); Graphics 에서색상과폰트활용 문자에만적용되는 Font와는달리 Color는문자열그리기, 도형그리기, 도형칠하기등색이필요한모든곳에사용된다. 색과폰트를설정하는 Graphics 메소드는다음과같다. void setcolor(color color) 그래픽색을 color로설정. 그리기시에색으로이용 void setfont(font font) 그래픽폰트를 font로설정. 문자열출력시폰트로이용 "Arial" 체와빨간색으로 "How much" 를 (30, 30) 위치에출력하면다음과같다. Graphics g; Font f = new Font("Arial", Font.ITALIC, 30); g.setfont(f); g.setcolor(color.red); g.drawstring("how much", 30, 30);
그래픽 CHAPTER 441 Color 와 Font 를이용하여문자열그리기 예제 -2 Color 와 Font 를이용하여그림과같이문자열을출력하라. "How much?" 는 "Arial" 체로, "This much!!" 는 Jokerman 체로한다. Jokerman 체는아쉽게도 한글을지원하지않는다. 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import javax.swing.*; import java.awt.*; public class GraphicsColorFontEx extends JFrame { (30,30) GraphicsColorFontEx() { settitle(" 문자열, Color, Font 사용예제 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); // 새로운패널을생성하여컨텐트팬으로사용 setsize(300, 300); setvisible(true); // JPanel을상속받아새패널구현 g.setcolor(color.blue); // 파란색지정 g.drawstring(" 자바가정말재밋다.~~", 30,30); // (30,30) 에문자열출력 g.setcolor(new Color(255, 0, 0)); // 빨간색지정 g.setfont(new Font("Arial", Font.ITALIC, 30)); g.drawstring("how much?", 30, 70); g.setcolor(new Color(0x00ff00ff)); // r=ff, g=00, b=ff, 즉보라색 for(int i=1; i<=4; i++) { g.setfont(new Font("Jokerman", Font.ITALIC, i*10)); g.drawstring("this much!!", 30, 60+i*40); public static void main(string [] args) { new GraphicsColorFontEx();
442 자바에센셜 JAVA Check Time 자바에서사용할수있는색은최대몇개인가? Graphics 객체 g 를이용하여파란색으로 (20, 20) 에 "BLUE" 문자열을출력하는코드를작성하라. Graphics 객체 g 를이용하여노란색으로 (100, 100) 에 20 픽셀크기의 "Arial" 체로 "Yes" 를출력하는코드를작성하라..3 도형그리기와칠하기 도형그리기 Graphics 를이용하여선, 타원, 사각형, 둥근모서리사각형, 원호, 폐다각형등을그릴 수있다. 우선선, 원, 사각형을그리는메소드를보면다음과같다. void drawline(int x1, int y1, int x2, int y2) (x1, y1) 에서 (x2, y2) 까지선을그린다. void drawoval(int x, int y, int w, int h) (x, y) 에서 w x h 크기의사각형에내접하는타원을그린다. void drawrect(int x, int y, int w, int h) (x, y) 에서 w x h 크기의사각형을그린다. void drawroundrect(int x, int y, int w, int h, int arcwidth, int archeight) arcwidth: 모서리원의수평반지름 archeight: 모서리원의수직반지름 (x, y) 에서 w x h 크기의사각형을그리되, 4개의모서리는 arcwidth와 archeight를이용하여원호로그린다. 이들메소드로도형을그리는코드예를들어보자. 예제 -3은 drawline() 을이용하여선을그리는코드샘플을보여주며, [ 그림 -2] 는예제소스의 drawline() 대신에 drawoval(), drawrect(), drawroundrect() 을이용하여원, 사각형, 둥근모서리사각형을그리는예이다.
그래픽 CHAPTER 443 선그리기 예제 -3 Graphics 의 drawline() 을이용하여컨텐트팬에 (20, 20) 에서 (100, 100) 까지빨간선을그리는 프로그램을작성하라. (20,20) (100,100) 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import javax.swing.*; import java.awt.*; public class GraphicsDrawLineEx extends JFrame { GraphicsDrawLineEx() { settitle("drawline 사용예제 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); setsize(200, 150); setvisible(true); g.setcolor(color.red); // 빨간색을선택한다. g.drawline(20, 20, 100, 100); (20, 20) 과 (100, 100) 의두점을연결하는 빨간색선을그린다. public static void main(string [] args) { new GraphicsDrawLineEx();
444 자바에센셜 JAVA g.setcolor(color.red); g.drawoval(20,20,80,80); (20,20) 80 80 g.setcolor(color.red); g.drawrect(20,20,80,80); (20,20) 80 80 g.setcolor(color.red); g.drawroundrect(20,20,120,80,40,60); (20,20) [ 예제 -3] 의소스에서 MyPanel 을수정하여이들도형을그린다. 40 120 80 60 [ 그림 -2] Graphics 를이용하여원, 사각형, 둥근모서리사각형그리기 원호와폐다각형그리기 Graphics 클래스의다음메소드를이용하면원호와폐다각형을그릴수있다. void drawarc(int x, int y, int w, int h, int startangle, int arcangle) startangle: 원호의시작각도 arcangle: 원호각도 (x, y) 에서 w x h 크기의사각형에내접하는원호를그린다. 3시방향이 0도기점이다. startangle 지점에서 arcangle 각도만큼원호를그린다. arcangle이양수이면반시계방향, 음수이면시계방향으로그린다. void drawpolygon(int []x, int []y, int n) x, y 배열에저장된점들중 n개를연결하는폐다각형을그린다. (x[0], y[0]), (x[1], y[1]),, (x[n-1], y[n-1]), (x[0], y[0]) 의점들을순서대로연결한다. 이들메소드를이용하여원호와폐다각형을그리는예는 [ 그림 -3] 과같다.
그래픽 CHAPTER 445 g.setcolor(color.red); g.drawarc(20,100,80,80,90,270); (20,100) 80 80 startangle=90 도 0 도 arcangle=270 도 g.setcolor(color.red); (80,40) int []x = {80,40,80,120; int []y = {40,120,200,120; g.drawpolygon(x, y, 4); (40,120) (120,120) (80,200) [ 예제 -3] 의소스에서 MyPanel을수정하여원호와폐다각형을그린다. [ 그림 -3] Graphics 를이용하여원호와폐다각형그리기 잠깐! 도형그리기의선두께는반드시 1 픽셀 Graphics의도형그리기는 1픽셀두께로만하며, 두께를선택할수없다. 외곽선의두께를다양하게그리고자한다면크기를달리하여여러번도형을그리든지 Graphics 2D를사용하면된다. 도형칠하기 도형칠하기란도형의외곽선과내부를동일한색으로칠하는기능이다. 도형의외곽선과내부를분리하여칠하는기능은없다. 칠하는색과외곽선의색을달리하고자하는경우, 도형내부를칠하고다른색으로외곽선을다시그려야한다. 도형칠하기메소드는다음과같이그리기메소드명에서 draw 대신에 fill로시작한다. fill drawrect() fillrect() drawarc() fillarc()
446 자바에센셜 JAVA 예제 -4 도형칠하기 Graphics 의칠하기메소드를이용하여그림과같은패널을작성하라. setcolor() 는칠하기색으로도사용 x[] 와 y[] 로부터 4 점으로구성된폐다각형칠하기 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import javax.swing.*; import java.awt.*; public class GraphicsFillEx extends JFrame { GraphicsFillEx() { settitle("fillxxx 사용예제 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); setsize(100, 350); setvisible(true); g.setcolor(color.red); g.fillrect(10,10,50,50); // 빨간색사각형칠하기 g.setcolor(color.blue); g.filloval(10,70,50,50); // 파란색타원칠하기 g.setcolor(color.green); g.fillroundrect(10,130,50,50,20,20); // 초록색둥근사각형칠하기 g.setcolor(color.magenta); g.fillarc(10,190,50,50,0,270); // 마젠타색원호칠하기 g.setcolor(color.orange); int []x ={30,10,30,60; int []y ={250,275,300,275; g.fillpolygon(x, y, 4); // 오렌지색다각형칠하기 public static void main(string [] args) { new GraphicsFillEx();
그래픽 CHAPTER 447 Graphics 객체 g 를이용하여다음도형을그리는코드를작성하라. (1) (10, 10) 에서 (30, 30) 까지의노란색선그리기 (2) 중심이 (20, 20) 이고높이가 10, 폭이 20 인사각형에내접하는타원그리기 (3) (10, 10), (5, 15), (15, 20) 으로구성되는삼각형칠하기. 삼각형의내부는빨간색 Check Time.4 이미지그리기 이미지그리는 2 가지방법 스윙에서이미지는다음 2가지방법으로그릴수있다. JLabel을이용한이미지그리기 Graphics의 drawimage() 로이미지그리기 첫번째방법은 10 장에서다룬것으로서 JLabel 컴포넌트를이용하는방법이다. 예 를들어, "images/apple.jpg" 이미지는다음과같이그린다. JLabel ImageIcon image = new ImageIcon("images/apple.jpg"); JLabel label = new JLabel(image); panel.add(label); 이방법은간편하고그리기쉽지만, 이미지의크기제어가어렵다. 두번째방법은 Graphics의 drawimage() 메소드를호출하여원하는위치에, 원하는크기로, 원하는비율로이미지를그리는방법이다. 이방법은이미지의크기를조절하거나이미지의일부분만그리는등다양하게이미지를출력할수있는장점이있으나, 이미지를그리는코드를직접작성해야하는부담이있다. drawimage() 잠깐! 이미지그리기 JLabel로이미지를그리는경우이미지가하나의컴포넌트가되므로마우스로이미지를움직이거나다른컨테이너에삽입하는등이미지관리가쉽다. 그러므로이미지변환같이이미지를특별하게다루는경우가아니라면 JLabel을이용하는것이좋다. JLabel의이미지는 JLabel의 paintcomponent() 에의해화면에그려진다. 그러므로 JLabel을상속받고 paintcomponent() 를오버라이딩하면이미지를변형하여그릴수도있다.
448 자바에센셜 JAVA Graphics 의 drawimage() 메소드 drawimage() 이미지를그리는 Graphics 의 drawimage() 메소드는몇가지유형이있다. 원본크기로그리기 원본크기로이미지를그리는 drawimage() 는다음과같다. boolean drawimage(image img, int x, int y, Color bgcolor, ImageObserver observer) boolean drawimage(image img, int x, int y, ImageObserver observer) img: 이미지객체 x, y: 이미지가그려질좌표 bgcolor: 이미지가투명한부분을가지고있을때투명한부분에칠해지는색상 observer: 이미지그리기의완료를통보받는객체 img를그래픽영역의 (x, y) 위치에 img의원본크기로그린다. 크기조절하여그리기 원본이미지를원하는크기로조절하여그리는 drawimage() 메소드는다음과같다. boolean drawimage (Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) boolean drawimage(image img, int x, int y, int width, int height, ImageObserver observer) width: 그려지는폭으로서픽셀단위 height: 그려지는높이로서픽셀단위 img를그래픽영역의 (x, y) 위치에 width x height 크기로조절하여그린다. Graphics 의이미지그리기 이제 drawimage() 를이용하여이미지를그리는과정을사례를통해알아보자. 이미지로딩 : Image 객체생성 이미지로딩 Image 이미지를그리기전에이미지를로딩하여 Image 객체를만들어야한다. 다음소스는 "images/image0.jpg" 파일로부터이미지를로딩하여 Image 객체를생성한다. image0. jpg 파일은프로젝트의 images 폴더에있어야한다. ImageIcon icon = new ImageIcon("images/image0.jpg"); // 파일로부터이미지로딩 Image img = icon.getimage(); // 이미지정보추출 img 를이용하면다음과같이이미지의폭과높이를알아낼수있다.
그래픽 CHAPTER 449 int width = img.getwidth(this); // 이미지의폭. this 는 ImageObserver 로서, null 도가능 int height = img.getheight(this); // 이미지의높이 (20, 20) 위치에이미지원본크기로그리기 img 이미지를 MyPanel 의 (20, 20) 에원본크기로그리는코드는다음과같다. g.drawimage(img, 20, 20, this); drawimage() 의마지막인자에는그리기완료를통보받는객체를지정하는데, 이코드에서 this를주었으므로통보를 JPanel이처리한다. 통보를무시하고자하면 null 을주기도한다. 대개 this나 null을사용한다. 이미지를 (20, 20) 위치에 100 100 크기로그리기 img 를 (20, 20) 위치에 100 100 크기로조절하여그리는코드는다음과같다. g.drawimage(img, 20, 20, 100, 100, this); 이미지를패널에꽉차도록그리기 img 를패널 (MyPanel) 에꽉차도록크기를조절하여그리는코드는다음과같다. g.drawimage(img, 0, 0, this.getwidth(), this.getheight(), this); 마우스로프레임의크기를변경하면 MyPanel의 paintcomponent() 가호출되며 drawimage() 가변경된패널크기에맞추어이미지를다시그리게된다.
450 자바에센셜 JAVA 예제 -5 원본크기로이미지그리기 그림과같이 "images/image0.jpg" 파일의이미지를패널의 (20, 20) 위치에원본크기로그리는 프로그램을작성하라. MyPanel() 이생성될때이미지를로딩하고, paintcomponent() 에서는그리기만한다. 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import javax.swing.*; import java.awt.*; public class GraphicsDrawImageEx1 extends JFrame { GraphicsDrawImageEx1() { settitle(" 원본크기로원하는위치에이미지그리기 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); setsize(300, 400); setvisible(true); ImageIcon icon = new ImageIcon("images/image0.jpg"); // 이미지로딩 Image img = icon.getimage(); // 이미지객체 // 이미지를패널의 (20,20) 에원래의크기로그린다. g.drawimage(img, 20, 20, this); (20, 20) public static void main(string [] args) { new GraphicsDrawImageEx1();
그래픽 CHAPTER 451 JPanel 크기에맞추어이미지그리기 예제 -6 그림과같이 "images/image0.jpg" 파일의이미지를패널에꽉차도록그려라. 프레임의크기가변하면, 패널의 paintcomponent() 가호출되어패널의크기에맞추어이미지가다 시그려진다. 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import javax.swing.*; import java.awt.*; public class GraphicsDrawImageEx2 extends JFrame { GraphicsDrawImageEx2() { settitle(" 패널의크기에맞추어이미지그리기 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); setsize(200, 300); setvisible(true); ImageIcon icon = new ImageIcon("images/image0.jpg"); // 이미지로딩 Image img = icon.getimage(); // 이미지객체 // 이미지를패널크기로조절하여그린다 g.drawimage(img, 0, 0, getwidth(), getheight(), this); 패널의폭과높이 public static void main(string [] args) { new GraphicsDrawImageEx2(); 프레임의크기가조절되면자동으로패널이다시그려지게되어패널의크기에맞추어이미지를다시그립니다.
452 자바에센셜 JAVA.5 repaint() 와그래픽응용 repaint() repaint() repaint() 는모든컴포넌트가가지고있는메소드로, 그래픽에서중요한기능을한다. 프로그램에서그래픽그리기를수행하거나, 컴포넌트의모양, 문자열, 크기, 색등을변경하는경우, 변경결과가화면에반영되려면컴포넌트의 paintcomponent() 메소드가다시실행되어야한다. 그렇지않으면변경결과가화면에반영되지않은채남아있게된다. 그렇다면프로그램이실행중컴포넌트의모양이나위치에변형을가하고, 직접 paintcomponent() 를호출하면될까? 이메소드는자바플랫폼이호출하며, 사용자가직접호출해서는안된다. 이문제에대한해결책은 repaint() 이다. repaint() 는자바플랫폼에게컴포넌트의페인팅을실행할것을간접적으로지시하는메소드이다. 개발자는프로그램에서컴포넌트의색, 모양, 크기, 텍스트등을변경한후 repaint() 를호출하여, 자바플랫폼이컴포넌트의 paintcomponent() 를호출하도록해야한다. 다음과같이 repaint() 를호출한다. component.repaint(); 컴포넌트를다시그리기위해서는컨테이너 ( 부모컴포넌트 ) 부터다시그리는것이좋다. 컴포넌트의모양이나위치가변경되었다면, 컨테이너 ( 부모컴포넌트 ) 에게자신의이전모양이나이전위치의잔상을지우도록해야하기때문이다. 다음과같이호출하면, component의부모컴포넌트부터다시그릴수있다. 부모컴포넌트를다시그리면당연히자신뿐아니라부모의모든자식들이다시페인팅된다. component.getparent().repaint(); repaint() 와마우스를이용한응용 repaint() 의활용을경험하기위해두개의예제를준비하였다. 하나는마우스드래깅으로타원을자유자재로그리는프로그램으로예제 -7에작성하였다. repaint() 없이는이프로그램의작성이불가능하므로, repaint() 의역할과중요성을확실히이해할수있을것이다. 이예제를실행하면마우스를드래깅하는동안타원이변해가는것을볼수있다. 두번째예는예제 -8로서, 여러개의선을그리고그려진선정보를기억하는사례이다. 다른응용에사용할수있는예제이니잘학습하기바란다.
그래픽 CHAPTER 453 repaint() 와마우스를이용한타원그리기 예제 -7 마우스를드래깅하여타원을그리는프로그램을작성하라. 마우스로한점을찍고드래깅을하면타원이그려진다. 드래깅하는동안타원모양을보기위해서는 mousedragged() 에서 repaint() 를호출해야한다. 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import javax.swing.*; import java.awt.*; import java.awt.event.*; public class GraphicsDrawOvalMouseEx extends JFrame { GraphicsDrawOvalMouseEx() { settitle(" 마우스드래깅으로타원그리기예제 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); setsize(300, 300); setvisible(true); public static void main(string [] args) { new GraphicsDrawOvalMouseEx(); // 타원을그릴패널작성. 이패널에마우스리스너구현 Point start=null, end=null; // 마우스의시작점과끝점 public MyPanel() { MyMouseListener listener = new MyMouseListener(); // 리스너생성 // listener를아래두리스너로공통으로등록해야한다. addmouselistener(listener); // Mouse 리스너등록 addmousemotionlistener(listener); // MouseMotion 리스너등록 class MyMouseListener extends MouseAdapter { // 마우스리스너 public void mousepressed(mouseevent e) { start = e.getpoint(); // 마우스포인터 ( 시작점 ) 를 start 객체에저장 public void mousedragged(mouseevent e) { end = e.getpoint(); // 마우스포인터 ( 끝점 ) 를 end 객체에저장 repaint(); // 패널의그리기요청주목 repaint() 가호출되면, 자바플랫폼에 의해 MyPanel의 paintcomponent() 가호출된다. 여기서 start와 end 사이의타원을그린다. 주목
454 자바에센셜 JAVA 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 // 패널에타원그리기 if(start == null) // 타원이만들어지지않았음 return; g.setcolor(color.blue); // 파란색선택 int x = Math.min(start.x, end.x); int y = Math.min(start.y, end.y); int width = Math.abs(start.x - end.x); int height = Math.abs(start.y - end.y); g.drawoval(x, y, width, height); // 타원그리기 예제 -8 repaint() 와마우스를이용한여러개의선그리기 그림과같이마우스를이용하여여러개의선을그리는프로그램을작성하라. 마우스를누르고드래깅하여놓으면선이그려진다. 여러개의선을그리기위해각선의위치를기억하는벡터를사용한다. 그린선이보이게하기위해서는 mousereleased() 에서 repaint() 를호출한다. 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 import javax.swing.*; import java.awt.*; import java.util.*; import java.awt.event.*; public class GraphicsDrawLineMouseEx extends JFrame { GraphicsDrawLineMouseEx() { settitle(" 마우스로여러개의선그리기예제 "); setdefaultcloseoperation(jframe.exit_on_close); setcontentpane(new MyPanel()); setsize(300, 300); setvisible(true); public static void main(string [] args) { new GraphicsDrawLineMouseEx();
그래픽 CHAPTER 455 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 // 선을그릴수있는패널을구현한다. // 이패널에 Mouse 리스너를구현한다. // 그려진선을모두저장하기위해시작점은 vstart 에 // 끝점은 vend 벡터에각각저장한다. Vector<Point> vstart = new Vector<Point>(); Vector<Point> vend = new Vector<Point>(); public MyPanel() { // Mouse 리스너를등록한다. // 이리스너는마우스버튼이눌러지면마우스포인터 ( 시작점 ) 를 vstart 벡터에저장하고 // 마우스버튼이놓여지면마우스포인터 ( 끝점 ) 를 vend 벡터에기억한다. addmouselistener(new MouseAdapter(){ public void mousepressed(mouseevent e) { Point startp = e.getpoint(); // 마우스포인터를알아낸다. vstart.add(startp); // 시작점을 vstart 에저장한다. public void mousereleased(mouseevent e) { Point endp = e.getpoint(); // 마우스포인터를알아낸다. vend.add(endp); // 끝점을 vend 에저장한다. ); // 패널의다시그리기를요청한다. repaint(); 주목 g.setcolor(color.blue); // 파란색을선택한다. // 벡터에저장된선을모두그린다. for(int i=0; i<vstart.size(); i++) { // vstart 벡터의크기는만들어진선의개수와동일 Point s = vstart.elementat(i); // 벡터에들어있는시작점을알아낸다. Point e = vend.elementat(i); // 벡터에들어있는끝점을알아낸다. 여러개의선을저장하기위해서 Vector<Point> 객체 vstart, vend 를생성하고시작점과끝점을각각따로저장합니다. mousepressed() 에서마우스가눌러진점 startp 와 mousereleased() 에서마우스의끝점 endp 를 vstart, vend 에각각저장합니다. 이제중요한것은그다음에 repaint() 를호출하는것입니다. 이호출로인해 MyPanel 이다시페인팅되고 paintcomponent() 가호출됩니다. paintcomponent() 메소드는 vstart 와 vend 에지금까지만들어진선을모두그립니다. // 시작점에서끝점까지선을그린다. g.drawline((int)s.getx(), (int)s.gety(), (int)e.getx(), (int)e.gety());
456 자바에센셜 JAVA 요약 summary 스윙컴포넌트그리기 각컴포넌트는자신의모양을그리는 ❶ 메소드를이용하여스스로그린다. 기존의컴포넌트를상속받아자신만의컴포넌트를만들고자하면 paintcomponent(graphics) 를오버라이딩하여야한다. ❷ 은그래픽을통해다양한 GUI를창출할수있는캔버스로유용하게사용된다. Graphics 그래픽이란개발자가스윙컴포넌트에의존하기않고, 선, 원, 이미지등으로직접화면을구성하는것을말한다. 그래픽을이용하면스윙컴포넌트를사용하는것보다자유로운 GUI를구성할수있고, 그리기속도가빨라게임등에주로활용된다. ❸ 는색상선택, 문자열그리기, 도형그리기및칠하기, 이미지그리기, 클리핑등의기능을제공한다. 문자열출력은 Graphics의 ❹ 메소드를이용한다. 색상은 Color를, 폰트는 Font를이용하여, Graphics의그리기색과글자체로각각사용할수있다. 도형그리기와칠하기 도형그리기는 Graphics 의 drawline(), drawrect(), drawoval(), drawroundrect(), drawarc(), drawpolygon() 등의메소드를이용한다. 도형칠하기는 Graphics의 fillrect(), filloval(), fillroundrect(), fillarc(), fillpolygon() 등의메소드를이용한다. 이미지그리기 이미지는 ❺ 컴포넌트를이용하는방법과 Graphics의 ❻ 메소드를이용하여그리는두가지방법이있다. Graphics는이미지를그리기위한여러 drawimage() 메소드를지원한다. repaint() 프로그램에서 Graphics를이용하여컴포넌트의모양이나색, 위치, 크기가변경하는경우, 컴포넌트가즉각변하지않을수있다. 변경된내용이화면에반영되려면그컴포넌트의 ❼ 가호출되어야하기때문이다. ❽ 메소드는모든컴포넌트가가진것으로, 자바플랫폼에게컴포넌트를다시그릴것을요청하는메소드이다. 컴포넌트의 repaint() 를호출하면자바플랫폼이컴포넌트의 paintcomponent() 를호출하여컴포넌트를다시그린다. repaint() 메소드는프로그램에서직접호출하면안된다. 컴포넌트를다시그리려면, 부모컴포넌트 ( 컨테이너 ) 의 repaint() 를호출하는것이좋다. 왜냐하면, 컴포넌트만다시그리면, 컨테이너에는컴포넌트의이전모양이그대로남아있을수있기때문이다. ANSWER 1 paintcomponent(graphics) 2 JPanel 3 Graphics 4 drawstring() 5 JLabel 6 drawimage() 7 paintcomponent() 8 repaint()
그래픽 CHAPTER 457 Open Challenge 파이차트그리기 목적 그래픽활용, 이벤트핸들링 파이차트를그려보자. 다음그림과같이 apple, cherry, strawberry, prune의 4종류의과일판매량을입력하면전체판매량에서백분율 (%) 을계산하여문자열과파이차트로동시에출력되도록하라. 텍스트필드컴포넌트에수를입력하고 <Enter> 키를치면 Action 이벤트가발생한다. Action 이벤트리스너에서백분율을계산하고파이차트를그린다. 난이도상 초기화면 수를입력하고 <Enter> 키를치면된다. 수를입력한화면
458 자바에센셜 JAVA 연습문제 EXERCISE 이론문제 홀수문제는정답이공개됩니다. 1. 모든스윙컴포넌트가오버라이딩하여가지고있는것으로자신의모양을그리는메소드는무엇인가? 그리고원래이메소드는어떤클래스에있는메소드인지말하라. 1 printcomponent(graphics g) 2 paintcontent(graphics g) 3 paintcomponent(graphics g) 4 repaint() 2. 스윙패키지에서지원되며빈캔버스와같이아무모양이없는컨테이너로서개발자가그래픽을통해다양한사용자인터페이스를그리고자할때사용하는클래스는? 1 JPanel 2 JFrame 3 JDialog 4 JCanvas 3. Graphics 클래스의기능이아닌것은? 1 이미지축소하여그리기 3 클리핑 2 폐다각형그리기 4 애니메이션 4. 다음설명중틀린것은? 1 JComponent를상속받아개발자는자신만의새로운컴포넌트를제작할수있다. 2 Graphics는 java.awt 패키지에속한클래스이다. 3 Graphics로선을그릴때선의두께를마음대로조절할수있다. 4 Graphics로다각형을칠할때외곽선과내부의색을다르게줄수없다. 5. 아래와같은 MyPanel 패널클래스가있을때, 다음각요청에따라그림을그리는코드를작성하라. Image img = new ImageIcon("test.jpg").getImage(); (1) 이미지를원본크기로 (10, 20) 위치에그리는코드를작성하라. (2) 패널안에상, 하, 좌, 우 10픽셀씩여백을두고그안에이미지가모두보이도록그리는코드를작성하라.
그래픽 CHAPTER 459 6. 아래와같은 MyPanel 패널클래스가있을때, 다음각요청에따라그림을그리는코드를한줄혹은두줄로작성하라. (1) 패널의 (100, 100) 에 30픽셀의 Times New Roman체로 "We win!!" 을출력하라. (2) 패널에꽉차는파란색의타원을그려라. 패널크기와함께타원의크기도변한다. 7. 자바로 GUI 를구성할때 JButton, JRadioButton 등컴포넌트를이용하거나또는그래픽을이용할수있다. 그래픽을이용하는장점은무엇인가? 8. 컴포넌트의 paintcomponent() 를응용프로그램에서직접호출하면안된다. 컴포넌트의 paintcomponent() 가실행되도록응용프로그램에서간접적으로할수있는방법은? 9. 다음코드를참고하여 super.paintcomponent(g) 의기능과호출이유를설명하라. import java.awt.*; import javax.swing.*; public class paintcomp extends JFrame { public paintcomp() { MyPanel p = new MyPanel(); // 패널생성 setcontentpane(p); // 패널을컨텐트팬으로설정 p.setbackground(color.yellow); // 패널의배경을노란색으로설정 setsize(300,300); setvisible(true); // 이코드의기능과호출이유를설명하라. g.drawstring("why", 100, 100); // (100,100) 에 Why 출력 public static void main(string[] args) { new paintcomp();
460 자바에센셜 JAVA 실습문제 홀수문제는정답이공개됩니다. 1. 다음과같이출력하는프로그램을작성하라. 난이도하 (1) 삼색원 (2) 오륜기 (3) 컨텐트팬에꽉차는마름모 (4) 컨텐트팬을 10 10 으로나누는격자그리기 2. FlowLayout 배치관리자를가진컨테이너의바탕에꽉차게 "back.jpg" 이미지를출력하고그위에 "Hello" 버튼이보이도록스윙프로그램을작성하라. "back.jpg" 이미지는독자임의로선택하면된다. 이문제는그래픽과컴포넌트를동시에사용할수있음을보여주기위한것이다. 때로는그래픽과컴포넌트를동시에사용하면효과적이다. 난이도하
그래픽 CHAPTER 461 3. 두개의이미지파일 a.jpg 와 b.jpg 를준비하고, JPanel 을상속받은패널에꽉차도록그래픽을이용하여두이미지를동일한크기로출력하는프로그램을작성하라. (1) 옆으로나란히출력하기 (2) 아래로나란히출력하기 난이도중 4. 앞의 2 번문제에주어진 "back.jpg" 을배경에출력하고그위에반지름이 20 픽셀인초록색원을만들어커서처럼마우스드래깅으로움직이는프로그램을작성하라. mousedragged() 에서 repaint() 를호출해야한다. 난이도중 5. (10,10) 에서시작하며, 마우스로점을찍으면점들을계속연결하여폐다각형을그리는프로그램을작성하라. mousepressed() 에서 repaint() 를호출해야한다. 난이도상 (10, 10) 점을 1 개찍을때점을 2 개찍을때점을여러개찍을때
462 자바에센셜 JAVA 6. "apple.jpg" 이미지를로딩하여그래픽으로패널의 (10,10) 위치에원본크기로출력하고, + 키를입력하면이미지를 10% 확대하고, - 키를입력하면 10% 축소하는프 로그램을작성하라. 난이도상 이미지의크기는다음과같이알아낼수있다. Image img; // 이미지가로딩되어있을때 int width = img.getwidth(this); // 이미지의폭, 픽셀단위 int height = img.getheight(this); // 이미지의높이, 픽셀단위 또한 keypressed() 에서 repaint() 를호출해야한다.