14. 2D 그래픽스
UI 프로그램에서 윈도우, 버튼, 이미지 등은 모두 화면에 그려진 2D 그래픽입니다. Swing은 개발자가 직접 2D 그래픽을 그릴 수 있도록 Java2D API를 제공합니다.
1. Canvas와 Graphics
그림을 그리기 위해서는 도화지(Canvas)와 붓(Graphics)이 필요합니다.
- Canvas: 그림이 그려지는 컴포넌트 (도화지)
- Graphics: 그림을 그리는 도구 (붓)
💡 비주얼 개념 잡기: Canvas와 Graphics의 관계
자바에서 화면에 무언가를 그릴 때는 미술 시간의 도화지와 붓을 생각하면 아주 간단합니다!

- Canvas (도화지): 그림이 그려지는 실제 컴포넌트(도화지)입니다. 도화지는 스스로 화면에 나타날 때(
paint()) 그림을 그릴 준비를 마칩니다. - Graphics (붓과 팔레트): 도화지에 선(
drawLine), 사각형(drawRect), 글자(drawString) 등을 직접 그려주는 도구(붓과 물감)입니다. - Repaint (도화지 새로 바꿔 그리기): 이미 그려진 도화지(화면)를 깨끗이 지우고 새로운 내용으로 다시 그리는 요청을 뜻합니다.
그리기 매커니즘
Canvas는 화면에 보일 준비가 되면 paint(Graphics g) 메서드를 호출하여 그림을 그립니다.
paint() 메서드가 호출되는 시점
- 윈도우가 처음 나타날 때
- 윈도우 크기가 변경될 때
- 윈도우가 다른 창에 가려졌다가 다시 나타날 때
- 프로그램에서 강제로
repaint()를 호출할 때
예제 (CanvasPaintExample)
- 실습 예제 파일: CanvasPaintExample.java (경로:
sample/sec14/exam01_paint/CanvasPaintExample.java) - 실행 방법:
# 1. 14_2d_graphics 디렉토리로 이동 후 컴파일 javac -d sample sample/sec14/exam01_paint/CanvasPaintExample.java # 2. 실행 java -cp sample sec14.exam01_paint.CanvasPaintExample
package sec14.exam01_paint;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class CanvasPaintExample extends JFrame {
public CanvasPaintExample() {
setTitle("paint() 메서드 호출 시점");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(new MyCanvas(), BorderLayout.CENTER);
setSize(300, 200);
}
// 사용자 정의 Canvas
class MyCanvas extends Canvas {
@Override
public void paint(Graphics g) {
g.drawString("윈도우 크기를 변경해보세요", 50, 80);
System.out.println("paint() 메서드 실행");
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new CanvasPaintExample().setVisible(true);
});
}
}
실행 결과 화면

2. 다시 그리기 (Repaint)
개발자가 직접 paint()를 호출할 수는 없습니다. 대신 repaint()를 호출하면 시스템이 update()를 거쳐 paint()를 호출합니다.
Repaint 흐름
repaint()호출update(Graphics g)호출: 기본적으로 화면을 지움 (배경색으로 채움)paint(Graphics g)호출: 다시 그림
화면이 깜빡거리는 것을 방지하거나, 이전 그림을 유지하려면 update() 메서드를 재정의하여 super.update(g)(화면 지우기)를 호출하지 않도록 해야 합니다.
@Override
public void update(Graphics g) {
paint(g); // 화면을 지우지 않고 바로 그리기
}
예제: 마우스 드래그로 그림 그리기 (RepaintExample)
- 실습 예제 파일: RepaintExample.java (경로:
sample/sec14/exam02_repaint/RepaintExample.java) - 실행 방법:
# 1. 14_2d_graphics 디렉토리로 이동 후 컴파일 javac -d sample sample/sec14/exam02_repaint/RepaintExample.java # 2. 실행 java -cp sample sec14.exam02_repaint.RepaintExample
package sec14.exam02_repaint;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class RepaintExample extends JFrame {
public RepaintExample() {
setTitle("재 드로잉");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(new MyCanvas(), BorderLayout.CENTER);
setSize(500, 400);
}
class MyCanvas extends Canvas implements MouseMotionListener {
private int x, y;
public MyCanvas() {
addMouseMotionListener(this);
}
@Override
public void update(Graphics g) {
paint(g); // 화면 지우기 생략
}
@Override
public void paint(Graphics g) {
g.drawString("*", x, y);
}
@Override
public void mouseDragged(MouseEvent e) {
x = e.getX();
y = e.getY();
repaint(); // 다시 그리기 요청
}
@Override
public void mouseMoved(MouseEvent e) {}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new RepaintExample().setVisible(true));
}
}
실행 결과 화면

3. 그래픽 주요 메서드
Graphics 객체는 다양한 그리기 메서드를 제공합니다.
색상 및 폰트 설정
| 메서드 | 설명 |
| :—————— | :—————————————————– |
| setColor(Color c) | 붓의 색상 설정 (예: Color.RED, new Color(r, g, b)) |
| setFont(Font f) | 글자 폰트 설정 |
Font 생성: new Font("글꼴이름", 스타일, 크기)
- 스타일:
Font.PLAIN,Font.BOLD,Font.ITALIC(조합 가능:Font.BOLD | Font.ITALIC)
도형 그리기 메서드
| 종류 | 외곽선 그리기 (draw...) | 내부 채우기 (fill...) | 설명 |
| :————– | :————————- | :———————- | :———————————- |
| 선 | drawLine(x1, y1, x2, y2) | - | (x1, y1)에서 (x2, y2)까지 선 그리기 |
| 사각형 | drawRect(x, y, w, h) | fillRect(x, y, w, h) | (x, y) 위치에 w x h 크기 사각형 |
| 원/타원 | drawOval(x, y, w, h) | fillOval(x, y, w, h) | 사각형 안에 내접하는 원/타원 |
| 둥근 사각형 | drawRoundRect(...) | fillRoundRect(...) | 모서리가 둥근 사각형 |
| 입체 사각형 | draw3DRect(...) | fill3DRect(...) | 음영 효과가 있는 사각형 |
| 호 (부채꼴) | drawArc(...) | fillArc(...) | 원의 일부분 |
| 다각형 | drawPolygon(...) | fillPolygon(...) | 점들의 배열을 이어 만든 다각형 |
예제 (ShapeExample)
- 실습 예제 파일: ShapeExample.java (경로:
sample/sec14/exam03_shape/ShapeExample.java) - 실행 방법:
# 1. 14_2d_graphics 디렉토리로 이동 후 컴파일 javac -d sample sample/sec14/exam03_shape/ShapeExample.java # 2. 실행 java -cp sample sec14.exam03_shape.ShapeExample
package sec14.exam03_shape;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class ShapeExample extends JFrame {
public ShapeExample() {
setTitle("도형 그리기 예제");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(new MyCanvas(), BorderLayout.CENTER);
setSize(400, 300);
}
class MyCanvas extends Canvas {
@Override
public void paint(Graphics g) {
g.setFont(new Font("맑은 고딕", Font.BOLD, 14));
g.drawString("다양한 도형 그리기", 20, 30);
g.drawOval(50, 50, 50, 50); // 원
g.setColor(Color.RED);
g.drawLine(50, 120, 150, 200); // 선
g.setColor(Color.BLUE);
g.drawRoundRect(200, 50, 120, 80, 30, 30); // 둥근 사각형
g.setColor(Color.GREEN);
g.fillRect(200, 150, 120, 60); // 채워진 사각형
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new ShapeExample().setVisible(true));
}
}
실행 결과 화면

4. 안티 알리아싱 (Anti-aliasing)
거친 계단 현상(Aliasing)을 없애고 부드럽게 그리는 기능입니다. Graphics2D로 캐스팅하여 설정합니다.
public void paint(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON
);
// 그리기 코드...
}
5. 이미지 그리기
이미지 파일을 로딩하여 화면에 그립니다.
이미지 로딩 방법
- Toolkit 이용:
Image img = Toolkit.getDefaultToolkit().getImage("경로/파일명"); - ImageIcon 이용:
Image img = new ImageIcon("경로/파일명").getImage(); - 리소스 경로 (classpath):
URL url = getClass().getResource("파일명"); Image img = Toolkit.getDefaultToolkit().getImage(url);
이미지 그리기
// g.drawImage(Image img, int x, int y, ImageObserver observer)
g.drawImage(img, 0, 0, this);
6. JPanel 배경 이미지 넣기
JPanel은 컨테이너이므로 자식 컴포넌트들 뒤에 배경을 그려야 합니다. 이를 위해 paintComponent 메서드를 재정의합니다.
호출 순서:
JPanel.paint()JPanel.paintComponent()(여기서 배경 그리기)JPanel.paintChildren()(자식 컴포넌트 그리기)
예제 (BackgroundImageExample)
- 실습 예제 파일: BackgroundImageExample.java (경로:
sample/sec14/exam06_background/BackgroundImageExample.java) - 실행 방법:
# 1. 14_2d_graphics 디렉토리로 이동 후 컴파일 javac -d sample sample/sec14/exam06_background/BackgroundImageExample.java # 2. 실행 (실행 전 같은 패키지 폴더 내의 bg.jpg 리소스가 필요합니다) java -cp sample sec14.exam06_background.BackgroundImageExample
package sec14.exam06_background;
import java.awt.BorderLayout;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class BackgroundImageExample extends JFrame {
public BackgroundImageExample() {
setTitle("JPanel 배경 이미지 넣기");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().add(new MyPanel(), BorderLayout.CENTER);
setSize(400, 300);
}
class MyPanel extends JPanel {
private Image bgImage;
public MyPanel() {
setLayout(null);
// 리소스 로드
bgImage = new ImageIcon(getClass().getResource("bg.jpg")).getImage();
// 자식 컴포넌트 추가
JButton button = new JButton("버튼");
button.setBounds(150, 120, 100, 30);
add(button);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g); // 기본 그리기 수행
if (bgImage != null) {
g.drawImage(bgImage, 0, 0, getWidth(), getHeight(), this); // 배경 그리기
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new BackgroundImageExample().setVisible(true));
}
}
#### 실행 결과 화면
