560 likes | 746 Views
제 10 주 그래픽프로그래밍 2. 제 10 주 강의 목표 Graphics 를 사용하여 임의의 Shape 을 그리는 법을 익힘 마우스이벤트 이용법을 익힘 타이머 이벤트 처리 및 애니메이션 효과를 구현하는 법을 익힘. Frame. import javax.swing.JFrame; public class EmptyFrameViewer { public static void main(String[] args) { JFrame frame = new JFrame();
E N D
제 10주 그래픽프로그래밍2 • 제 10주 강의 목표 • Graphics를 사용하여 임의의 Shape을 그리는 법을 익힘 • 마우스이벤트 이용법을 익힘 • 타이머 이벤트 처리 및 애니메이션 효과를 구현하는 법을 익힘 강원대학교
Frame 강원대학교
import javax.swing.JFrame; public class EmptyFrameViewer { public static void main(String[] args) { JFrame frame = new JFrame(); final int FRAME_WIDTH = 300; final int FRAME_HEIGHT = 400; frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setTitle("An Empty Frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 강원대학교
도형 그리기 • 프레임 안에 도형을 그리기 위해서는 그림 그리는 기능을 가진 부품(JComponent)을 프레임에 넣어주어야 함 • JComponent 객체는 paintComponent 메소드를 가짐 • paintComponent 메소드는 필요할 때마다 시스템에 의해 자동으로 호출됨 • 필요한 때 • 프로그램이 처음 실행될 때 • 프레임을 아이콘으로 최소화했다가 다시 창으로 복원시킬 때 • 프레임이 다른 윈도우에 의해 가려졌다가 나타날 때 • 마우스 드래그를 이용해 프레임을 이동시킬 때 등 강원대학교
import javax.swing.*; public class EmptyFrameViewer { public static void main(String[] args) { JFrame frame = new JFrame(); final int FRAME_WIDTH = 300; final int FRAME_HEIGHT = 400; frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setTitle("An Empty Frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JComponent component = new JComponent(); // 부품을 구성 frame.add(component); // 부품을 프레임에 넣음 frame.setVisible(true); } } 강원대학교
도형 그리기 • JComponent객체가 가지고 있는 paintComponent메소드는 화면에 아무것도 그리지 않음 • 화면에 도형을 그리려면 도형 그리는 기능을 갖도록 Jcomponent를 수정하여 프레임에 넣어 줘야 함 • Jcomponent를 수정하여 새로운 부품을 만드는 방법 public class RectangleComponentextends JComponent{ public void paintComponent(Graphics g) { // Recover Graphics2D Graphics2D g2 = (Graphics2D) g; . . . }} 강원대학교
RectangleComponent.java public class RectangleComponent extends JComponent{ public void paintComponent(Graphics g) { // Recover Graphics2D Graphics2D g2 = (Graphics2D) g; Rectangle box = new Rectangle(5, 10, 20, 30); g2.draw(box); }} • RectanlgeComponent 클래스는 수퍼클래스인 JComponent의 paintComponent 메소드를 상속하여 이를 재정의(override)함 • JComponent의 paintComponent 메소드는 아무것도 그리지 않음 • 재정의된 paintComponent 메소드는 사각형 인스턴스를 하나 구성하고 이것을 화면에 그림 강원대학교
RectangleViewer.java import javax.swing.*; public class RectangleViewer { public static void main(String[] args) { JFrame frame = new JFrame(); final int FRAME_WIDTH = 300; final int FRAME_HEIGHT = 400; frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setTitle("A Rectangle Frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); RectangleComponent component = new RectangleComponent(); frame.add(component); // 부품을 프레임에 넣음 frame.setVisible(true); } } 강원대학교
RectangleComponent.java import javax.swing.JComponent; import java.awt.Rectangle; import java.awt.Graphics; import java.awt.Graphics2D; public class RectangleComponent extends JComponent{ public void paintComponent(Graphics g) { // Recover Graphics2D Graphics2D g2 = (Graphics2D) g; Rectangle box = new Rectangle(5, 10, 20, 30); g2.draw(box); box.translate(15, 25); g2.draw(box); }} 강원대학교
컴파일할 때의 파일간 종속성 • (같은 폴더에) RectanlgeComponent.java 파일 없이 RectanlgeViewer.java를 컴파일하려고 하면 안됨 • RectangleViewer가 RectangleComponet를 사용하기 때문 • 반면 RectanlgeComponent.java는 RectanlgeViewer.java 파일 없이도 컴파일 가능 강원대학교
Graphical Shapes • Rectangle, Ellipse2D.Double, Line2D.Double 등 • API 문서에서 java.awt.Shape을 찾아보면 Shape에 속하는 도형들을 더 볼 수 있음 강원대학교
Ellipse Graphical Shapes • Ellipse2D.Double은 Ellipse2D의 내부클래스(innerclass)임 • Ellipse2D.Double를 사용하기 위해서는 import java.awt.geom.Ellipse2D Ellipse2D.Double ellipse = new Ellipse2D.Double(x, y, width, height);g2.draw(ellipse); 강원대학교
Drawing Lines • To construct a line:or, Line2D.Double segment = new Line2D.Double(x1, y1, x2, y2); Point2D.Double from = new Point2D.Double(x1, y1);Point2D.Double to = new Point2D.Double(x2, y2);Line2D.Double segment = new Line2D.Double(from, to); • To draw the line: g.draw(segment); 강원대학교
Drawing Strings g2.drawString("Message", 50, 100); 강원대학교
Colors • Standard colors: Color 클래스에 static 필드로 정의되어 있음 • Color.BLUE, Color.RED, Color.PINK etc. • static 필드: 개별 인스턴스에 속하지 않고 클래스에 하나만 정의되는 필드 • 필드: 클래스 내부이면서 메소드 외부에 선언된 변수, 상수, 객체 강원대학교
칼라 사각형 그리기 public void paintComponent(Graphics g){ Graphics2D g2 = (Graphics2D) g; g2.setColor(Color.RED); g2.fill(new Rectangle(0, 0, 200, 200)); g2.setColor(Color.YELLOW); g2.fill(new Rectangle(50, 50, 100, 100)); } 강원대학교
임의 칼라 사각형 그리기 Color(float r, float g, float b) – r, g, b는 0.0-1.0 Color(int r, int g, int b) - r, g, b는 0-255 public void paintComponent(Graphics g){ Graphics2D g2 = (Graphics2D) g; g2.setColor(new Color(0.5f, 0.6f, 0.3f)); g2.fill(new Rectangle(0, 0, 200, 200)); g2.setColor(new Color(25, 200, 224)); g2.fill(new Rectangle(50, 50, 100, 100)); } 강원대학교
복잡한 모양 그리기 강원대학교
import javax.swing.JFrame; public class CarViewer { public static void main(String[] args) { JFrame frame = new JFrame(); final int FRAME_WIDTH = 300; final int FRAME_HEIGHT = 400; frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setTitle("Two cars"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); CarComponent component = new CarComponent(); frame.add(component); frame.setVisible(true); } } 강원대학교
위치 HEIGHT WIDTH import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JComponent; public class CarComponent extends JComponent { public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; Car car1 = new Car(0, 0); int x = getWidth() - Car.WIDTH; int y = getHeight() - Car.HEIGHT; Car car2 = new Car(x, y); car1.render(g2); car2.render(g2); } } 강원대학교
import java.awt.Graphics; import java.awt.Graphics2D; import javax.swing.JComponent; public class CarComponent extends JComponent { public void paintComponent(Graphics g) { Graphics2D g2 = (Graphics2D) g; Car car1 = new Car(0, 0); int x = getWidth() - Car.WIDTH; int y = getHeight() - Car.HEIGHT; Car car2 = new Car(x, y); car1.render(g2); car2.render(g2); } } CarComponent에 그림을 그리기 위한 도구 • getWidth, getHeight는 paintComponent를 실행하고 있는 CarComponent 객체에 호출됨 • 윈도우 크기를 조정하면 paintComponent가 호출되고 자동차의 위치가 재계산됨 (프로그램을 실행한 후 마우스를 드래그하여 윈도우 크기를 바꿔보세요!) 강원대학교
복잡한 모양 그리기 강원대학교
public class Car { public Car(int x, int y) { xLeft = x; yTop = y; } public void render(Graphics2D g2) { g2.draw(body); g2.draw(frontTire); g2.draw(rearTire); g2.draw(frontWindshield); g2.draw(roofTop); g2.draw(rearWindshield); } public static int WIDTH = 60; // static field public static int HEIGHT = 30; // static field private int xLeft; // 인스턴스 필드 private int yTop; // 인스턴스 필드 } 미완성! 강원대학교
import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Point2D; /** A car shape that can be positioned anywhere on the screen. */ public class Car { /** Constructs a car with a given top left corner @param x the x coordinate of the top left corner @param y the y coordinate of the top left corner */ public Car(int x, int y) { xLeft = x; yTop = y; } 강원대학교
/** Draws the car. @param g2 the graphics context */ public void render(Graphics2D g2) { Rectangle body = new Rectangle(xLeft, yTop + 10, 60, 10); Ellipse2D.Double frontTire = new Ellipse2D.Double(xLeft + 10, yTop + 20, 10, 10); Ellipse2D.Double rearTire = new Ellipse2D.Double(xLeft + 40, yTop + 20, 10, 10); // The bottom of the front windshield Point2D.Double r1 = new Point2D.Double(xLeft + 10, yTop + 10); // The front of the roof Point2D.Double r2 = new Point2D.Double(xLeft + 20, yTop); // The rear of the roof Point2D.Double r3 = new Point2D.Double(xLeft + 40, yTop); // The bottom of the rear windshield Point2D.Double r4 강원대학교
Line2D.Double frontWindshield = new Line2D.Double(r1, r2); Line2D.Double roofTop = new Line2D.Double(r2, r3); Line2D.Double rearWindshield = new Line2D.Double(r3, r4); g2.draw(body); g2.draw(frontTire); g2.draw(rearTire); g2.draw(frontWindshield); g2.draw(roofTop); g2.draw(rearWindshield); } public static int WIDTH = 60; public static int HEIGHT = 30; private int xLeft; private int yTop; } 강원대학교
Reading Text Input String input = JOptionPane.showInputDialog("Enter x");double x = Double.parseDouble(input); 강원대학교
마우스 이벤트 처리 강원대학교
Mouse Events • 마우스 이벤트를 처리하기 위해서는 마우스리스너를 사용 • 마우스리스너는 MouseListener 인터페이스를 구현해야 함 public interface MouseListener { void mousePressed(MouseEvent event); // Called when a mouse button has been pressed on a component void mouseReleased(MouseEvent event); // Called when a mouse button has been released on a component void mouseClicked(MouseEvent event); // Called when the mouse has been clicked on a component void mouseEntered(MouseEvent event); // Called when the mouse enters a component void mouseExited(MouseEvent event); // Called when the mouse exits a component } 강원대학교
마우스 리스너 구현과 등록 public class MyMouseListener implements MouseListener { // Implements five methods } MouseListener listener = new MyMouseListener(); component.addMouseListener(listener); 강원대학교
Mouse Event 처리 프로그램 예 • RectangleComponentViewer • 마우스를 클릭하면 그 위치로 사각형이 이동 강원대학교
public class RectangleComponent extends JComponent { public RectangleComponent() { box = new Rectangle(BOX_X, BOX_Y, BOX_WIDTH, BOX_HEIGHT); } public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; g2.draw(box); } public void moveTo(int x, int y) { box.setLocation(x, y); repaint(); } private Rectangle box; } 강원대학교
public class RectangleComponentViewer { public static void main(String[] args) { final RectangleComponent component = new RectangleComponent(); class MousePressListener implements MouseListener { public void mousePressed(MouseEvent event) { int x = event.getX(); int y = event.getY(); component.moveTo(x, y); } public void mouseReleased(MouseEvent event) {} public void mouseClicked(MouseEvent event) {} public void mouseEntered(MouseEvent event) {} public void mouseExited(MouseEvent event) {} } MouseListener listener = new MousePressListener(); component.addMouseListener(listener); JFrame frame = new JFrame(); frame.add(component); frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } 강원대학교
File RectangleComponent.java 01: import java.awt.Graphics; 02: import java.awt.Graphics2D; 03: import java.awt.Rectangle; 04: import javax.swing.JComponent; 05: 06: /** 07: This component lets the user move a rectangle by 08: clicking the mouse. 09: */ 10:public class RectangleComponent extends JComponent 11: { 12:public RectangleComponent() 13: { 14: // The rectangle that the paint method draws 15: box = new Rectangle(BOX_X, BOX_Y, 16: BOX_WIDTH, BOX_HEIGHT); 17: } 18: 강원대학교
File RectangleComponent.java 19:public void paintComponent(Graphics g) 20: { 21: super.paintComponent(g); 22: Graphics2D g2 = (Graphics2D) g; 23: 24: g2.draw(box); 25: } 26: 27: /** 28: Moves the rectangle to the given location. 29: @param x the x-position of the new location 30: @param y the y-position of the new location 31: */ 32:public void moveTo(int x, int y) 33: { 34: box.setLocation(x, y); 35: repaint(); 36: } 강원대학교
File RectangleComponent.java 37: 38: private Rectangle box; 39: 40:private static final int BOX_X = 100; 41:private static final int BOX_Y = 100; 42:private static final int BOX_WIDTH = 20; 43:private static final int BOX_HEIGHT = 30; 44: } 강원대학교
마우스 리스너 구현 class MousePressListener implements MouseListener { public void mousePressed(MouseEvent event) { int x = event.getX(); int y = event.getY(); component.moveTo(x, y); } // Do-nothing methods public void mouseReleased(MouseEvent event) {} public void mouseClicked(MouseEvent event) {} public void mouseEntered(MouseEvent event) {} public void mouseExited(MouseEvent event) {} } • MouseListener 인터페이스에 정해져 있는 다섯개의 메소드를 모두 구현해야 함 강원대학교
RectangleComponentViewer2.java 01: import java.awt.event.MouseListener; 02: import java.awt.event.MouseEvent; 03: import javax.swing.JFrame; 04: 05: /** 06: This program displays a RectangleComponent. 07: */ 08:public class RectangleComponentViewer 09: { 10:public static void main(String[] args) 11: { 12:final RectangleComponent component = new RectangleComponent(); 13: 14: // Add mouse press listener 15: 16: class MousePressListener implements MouseListener 17: { 강원대학교
RectangleComponentViewer2.java 18:public void mousePressed(MouseEvent event) 19: { 20:int x = event.getX(); 21:int y = event.getY(); 22: component.moveTo(x, y); 23: } 24: 25:// Do-nothing methods 26:public void mouseReleased(MouseEvent event) {} 27:public void mouseClicked(MouseEvent event) {} 28:public void mouseEntered(MouseEvent event) {} 29:public void mouseExited(MouseEvent event) {} 30: } 31: 32: MouseListener listener = new MousePressListener(); 33: component.addMouseListener(listener); 34: 강원대학교
RectangleComponentViewer2.java 35: JFrame frame = new JFrame(); 36: frame.add(component); 37: 38: frame.setSize(FRAME_WIDTH, FRAME_HEIGHT); 39: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 40: frame.setVisible(true); 41: } 42: 43:private static final int FRAME_WIDTH = 300; 44: private static final int FRAME_HEIGHT = 400; 45: } 강원대학교
타이머이벤트 처리 애니메이션 강원대학교
Processing Timer Events • javax.swing.Timer는 일정 시간 간격으로 액션이벤트를 발생시킨다. • 객체 상태를 일정 시간 간격으로 갱신하고자 할 때 사용 • 타이머에게 액션이벤트 리스너를 등록해 놓으면 액션이벤트가 발생될 때마다 액션이벤트 리스너의 actionPerformed 메소드가 호출됨 - callback! class MyListener implements ActionListener{ void actionPerformed(ActionEvent event) { // 타이머에서 액션이벤트가 발생할 때마다 // 이곳에 적어주는 액션이 실행됨 }} 강원대학교
Processing Timer Events • 액션 리스너를 타이머에 등록함 MyListener listener = new MyListener();Timer t = new Timer(interval, listener);t.start();// 타이머 쓰레드 시작 등록 MyListener actionPerformed Timer 주기적으로 이벤트 발생 actionPerformed 메소드 실행 (callback) 강원대학교
Example: Countdown • Example: a timer that counts down to zero 강원대학교
File TimeTester.java 01: import java.awt.event.ActionEvent; 02: import java.awt.event.ActionListener; 03: import javax.swing.JOptionPane; 04: import javax.swing.Timer; 05: 06: /** 07: This program tests the Timer class. 08: */ 09:public class TimerTester 10: { 11:public static void main(String[] args) 12: { 13:classCountDownimplementsActionListener 14: { 15:public CountDown(int initialCount) 16: { 17: count = initialCount; 18: } 강원대학교
File TimeTester.java 19: 20:public void actionPerformed(ActionEvent event) 21: { 22:if (count >= 0) 23: System.out.println(count); 24:if (count == 0) 25: System.out.println("Liftoff!"); 26: count--; 27: } 28: 29:private int count; 30: } 31: 32: CountDown listener = new CountDown(10); 33: 34:final int DELAY = 1000; // Milliseconds between // timer ticks 강원대학교
File TimeTester.java 35: Timer t = new Timer(DELAY, listener); 36: t.start(); 37: 38: JOptionPane.showMessageDialog(null, "Quit?"); 39: System.exit(0); 40: } 41: } 강원대학교
애니메이션 프로그램 기본 형식 class Mover implements ActionListener { public void actionPerformed(ActionEvent event) { // Move the rectangle } } ActionListener listener = new Mover(); final int DELAY = 100; // Milliseconds between timer ticks Timer t = new Timer(DELAY, listener); t.start(); 강원대학교
Accessing Surrounding Variables • Inner 클래스의 메소드에서는 바깥 클래스의 변수에 접근할 수 있음 public static void main(String[] args) { . . . final Rectangle box = new Rectangle(5, 10, 20, 30); class Mover implements ActionListener { public void actionPerformed(ActionEvent event) { // Move the rectangle box.translate(1, 1); } } . . . } 강원대학교
File TimeTester2.java 01: import java.awt.Rectangle; 02: import java.awt.event.ActionEvent; 03: import java.awt.event.ActionListener; 04: import javax.swing.JOptionPane; 05: import javax.swing.Timer; 06: 07: /** 08: This program uses a timer to move a rectangle once per second. 09: */ 10:public class TimerTester2 11: { 12:public static void main(String[] args) 13: { 14:final Rectangle box = new Rectangle(5, 10, 20, 30); 15: 16:class Mover implements ActionListener 17: { 강원대학교