1. 🔥 paintComponent

지금까지 배운 다양한 컴포넌트들은 해당 컨테이너 내에서 그림을 그리며(색칠)하며 호출된다.

디폴트로 컴포넌트는 paintComponent라는 메서드를 호출한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import java.awt.Graphics; // Graphics클래스

import javax.swing.JFrame;
import javax.swing.JPanel;

class DrawingInSwingPanel extends JPanel{
    DrawingInSwingPanel(){

    }
    @Override // paintComponent메서드 오버라이딩
    public void paintComponent(Graphics g) {
        super.paintComponent(g); // 부모메서드 호출
        System.out.println("paint");
    }
}

public class App extends JFrame {
    App(){
        setTitle("component Draw");
        setSize(600,600);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        add(new DrawingInSwingPanel());

        setVisible(true);
    }
    public static void main(String[] args){
        new App();
    }
}
  • 이 코드를 실행 시키면 보는 것과 같이 GUI가 출력되는데 해당 창을 늘리기, 줄이기, 최대화, 최소화 등등 컴포넌트를 다시 그려야하는 상황이 온다면 해당 매서드가 호출된다.

  • 해당 메서드를 오버라이딩할 경우 말 그대로 재정의가 되기 때문에 해당 메서드의 디폴트 즉, 부모의 메서드가 실행되지 않는다.(위험) 따라서 super키워드를 통해 부모 메서드 호출 후 재정의

Graphics g

그림을 그린다는 것-> 해당 컴포넌트의 메모리의 구성요소(각 점의 메모리), 그래픽카드에 존재 하는 픽셀 메모리.. 그래픽카드에 접근하여 해당 메모리값을 바꾸는 것이 그림을 칠하는 방식이다.

그렇다면 사용자가 하드웨어의 접근까지 다뤄야 하는 것인가?

  • swing에서 paintComponent(Graphics g)를 자동으로 호출하며 Graphics라는 객체로 실제 이미지의 메모리로 연결해준다.

따라서 사용자는 g를 사용해서 컴포넌트에 그림을 그리면 된다..!

1.1. 실습 - 사각형 그리기

1
2
3
4
5
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawRect(100, 100, 100, 100);
        // 가로(위치),세로(위치),너비,높이
    }

1.2. 정리

  • 스윙의 기본 철학
    • 모든 GUI컴포넌트들은 자신의 모양을 스스로 그린다.
    • 컨테이너들은 자신을 그린 후, 그 위의 자식들에게 그리기를 지시한다.
  • public void paintComponent(Graphics g)
    • 스윙 컴포넌트가 자신의 모양을 그리는 메서드
    • JComponent의 메서드: 모든 스윙 컴포넌트가 이 메서드를 가지고 있음
    • 컴포넌트가 그려져야하는 시점마다 호출된다.(크기 변경, 최소화,최대화 등등)
  • Graphics객체
    • java.awt.Graphics
    • 컴포넌트 그리기에 필요한 도구를 제공하는 객체
      • 색상선택, 문자열 출력, 도형그리기, 도형 칠하기, 이미지 출력, 클리핑
    • 사용자가 원하는 모양을 그리고자 할 때 paintComponent(Graphics g)오버라이딩

1.3. 실습 - 폰트

//코드 수정할 것

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setColor(Color.RED); // 색 결정
        g.drawString("세종대학교", 100, 100);
        g.setColor(new Color(255,0,255)); // 새로운 컬러 만들어서 할당
        g.drawRect(100, 100, 100, 100);

        Font f = new Font("굴림",Font.ITALIC,50);
        //폰트 객체 만들기(글씨체, 타입, 크기)
        g.setFont(f);//폰트 적용
        g.setColor(Color.GREEN);
        g.drawString("폰트 테스트", 200, 200);
    }

폰트 및 글씨색을 결정하여 String을 그리는 모습이다.

1.4. 실습 - 도형 그리기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class DrawingInSwingPanel extends JPanel{
    DrawingInSwingPanel(){

    }
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Dimension size = this.getSize();
        int w = size.width;
        int h = size.height;
        g.setColor(Color.GREEN);
        g.drawLine(0, 0, w,h);
        g.setColor(Color.BLACK);
        g.drawRect(100, 100, 200, 200);
        g.drawOval(200, 200, 100, 100);
        g.drawRoundRect(200, 100, 100, 100, 10, 10);
    }
}

draw를 fill로 바꾸면 내부도 채워서 그릴 수 있다 ex) fillRect()

  • drawLine: 선 그리기
  • drawRect: 사각형 그리기
  • drawOval: 사격형에 내접하는 원 그리기
  • drawRoundRect: 모서리가 둥근 각형
  • 추가적인 draw..가 있다! 알아볼껏

Dimension

  • Dimension클래스는 사이즈를 담을 수 있는 클래스(getSize반환값)

추가(신기한거 만들기 예제…)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class DrawingInSwingPanel extends JPanel{
    DrawingInSwingPanel(){

    }
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Dimension size = this.getSize();
        int w = size.width;
        int h = size.height;
        int div = 40;
        float dw = (float)w/div;
        float dh = (float)h/div;
        for(int i = 0; i < div; i++){
            g.drawLine(0, (int)(dh*i), (int)(dw*i), h);
        }
        for(int i = 0; i < 10; i++){
          g.setColor(new Color(i*25, i*25, i*25));
          g.fillRect(200+10*i, 200+10*i, 200-i*20, 200-i*20);
        }
    }
}

1.5. 실습 - 마우스로 선 그리기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class DrawingInSwingPanel extends JPanel implements MouseListener{
    int x1,y1; //멤버 필드 선언 시작좌표
    int x2,y2; //종료 좌표

    DrawingInSwingPanel(){
        addMouseListener(this);  
    } 
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawLine(x1, y1, x2, y2); //선 그리기
    }
    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {
        x1 = e.getX();
        y1 = e.getY();
    }
    public void mouseReleased(MouseEvent e) {
        x2 = e.getX();
        y2 = e.getY();
        repaint(); //paintComponent호출 요청
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

paintComponent는 자동으로 호출되기 때문에 사용자가 직접 호출할 수 없다 하지만, 간접적으로 현재 컴포넌트를 다시 그려달라고 요청은 가능 repaint()

repaint는 이벤트 분배 쓰레드에 요청을 보낸다.

추가

  • revaildate(): 배치관리자에게 컴포넌트들을 다시 배치하도록 지시하는 컴포넌트

1.6. 실습 - 마우스로 선 그리기(여러개)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class DrawingInSwingPanel extends JPanel implements MouseListener{
    ArrayList<Integer> x1 = new ArrayList<>();
    ArrayList<Integer> x2 = new ArrayList<>();
    ArrayList<Integer> y1 = new ArrayList<>();
    ArrayList<Integer> y2 = new ArrayList<>();

    DrawingInSwingPanel(){
        addMouseListener(this);  
    } 
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        for(int i = 0; i<x1.size();i++){
            g.drawLine(x1.get(i), y1.get(i), x2.get(i), y2.get(i));
        }
    }
    public void mouseClicked(MouseEvent e) {}
    public void mousePressed(MouseEvent e) {
        x1.add(e.getX());
        y1.add(e.getY());
    }
    public void mouseReleased(MouseEvent e) {
        x2.add(e.getX());
        y2.add(e.getY());
        repaint(); // 중요
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}
  • 선이 생길때 마다 그 선을 저장해야 하므로 ArrayList를 사용하여 선분을 저장한다.

1.7. 정리

스윙의 페인트

  • void paint(Graphics g): 컴포넌트 자신과 모든 자손을 그리기 중요
    • 아래는 paint의 호출 순서
  • void paintComponent(Graphics g): 컴포넌트 자신의 내부모양 그리기
  • void paintBorder(Graphics g): 컴포넌트의 외곽 그리기
  • void paintChildren(Graphics g): 컴포넌트의 자식 그리기(컨테이너의 경우)

paint한다는 것은 처음부터 다시 그리는것..!

repaint()로 컴포넌트를 다시 그림..

1.8. 실습 - 선분 드래그, 색 선택

1
2
3
4
5
6
7
8
9
10
11
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
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

class MyPanel extends JPanel implements MouseListener, MouseMotionListener{
    private class ColorButton extends JButton{
        Color color;
        ColorButton(String str, Color c){
            super(str);
            color = c;
        }
        @Override
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            int w = getWidth();
            int h = getHeight();
            g.setColor(color);
            g.fillRect(2, 2, w - 4, h - 4);
        }
    }
    
    private class MyLine{
        private int x1,y1,x2,y2;
        private Color color = Color.BLACK;
        MyLine(int _x1,int _y1,int _x2,int _y2, Color _c){
            x1 = _x1;
            y1 = _y1;
            x2 = _x2;
            y2 = _y2;
            color = _c;
        }
        void draw(Graphics g){
            g.setColor(color);
            g.drawLine(x1, y1, x2, y2);
        }
        void setEncPosition(int _x,int _y){
            x2 = _x;
            y2 = _y;
        }
    }

    ArrayList<MyLine> lines = new ArrayList<>();
    Color color = Color.BLACK;

    MyPanel(){
        addMouseListener(this);
        addMouseMotionListener(this);
    
        ColorButton red = new ColorButton("r", Color.RED);
        ColorButton blue = new ColorButton("b", Color.BLUE);
        ColorButton green = new ColorButton("g", Color.GREEN);

        red.addActionListener((e) -> {color = red.color;});
        blue.addActionListener((e) -> {color = blue.color;});
        green.addActionListener((e) -> {color = green.color;});

        add(red);
        add(blue);
        add(green);
    }
    int x,y;
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for(int i = 0; i < lines.size(); i++)
            lines.get(i).draw(g);
    }
    public void mouseClicked(MouseEvent e) {}
    int mouseButton = -1;
    public void mousePressed(MouseEvent e) {
        mouseButton = e.getButton();
        if(e.getButton() == MouseEvent.BUTTON1)
            lines.add(new MyLine(e.getX(),e.getY(), e.getX(),e.getY(),color));
    }
    public void mouseReleased(MouseEvent e) {
        repaint();
        mouseButton = -1;
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseDragged(MouseEvent e) {
        if(mouseButton == MouseEvent.BUTTON1){
            lines.get(lines.size() - 1).setEncPosition(e.getX(),e.getY());
            repaint();
        }
        
    }
    public void mouseMoved(MouseEvent e) {
        // TODO Auto-generated method stub
        
    }
}

public class My extends JFrame{
    My(){
        setSize(500,500);
        setTitle("Title");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        
        add(new MyPanel());

        setVisible(true);
    }
    public static void main(String[] args){
        new My();
    } 
}

1.9. 실습 - 커브(선)그리기

1
2
3
4
5
6
7
8
9
10
11
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
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import java.awt.GridLayout;
import java.awt.Point;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;


class MyPanel extends JPanel implements MouseListener, MouseMotionListener{
    private class ColorButton extends JButton{
        Color color;
        ColorButton(String str, Color c){
            super(str);
            color = c;
        }
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            int w = getWidth();
            int h = getHeight();
            g.setColor(color);
            g.fillRect(2, 2, w - 4, h - 4);
        }
    }
    
    private class MyLine{
        private int x1,y1,x2,y2;
        private Color color = Color.BLACK;
        MyLine(int _x1,int _y1,int _x2,int _y2, Color _c){
            x1 = _x1;
            y1 = _y1;
            x2 = _x2;
            y2 = _y2;
            color = _c;
        }
        void draw(Graphics g){
            g.setColor(color);
            g.drawLine(x1, y1, x2, y2);
        }
        void setEncPosition(int _x,int _y){
            x2 = _x;
            y2 = _y;
        }
    }

    ArrayList<MyLine> lines = new ArrayList<>();
    Color color = Color.BLACK;

    MyPanel(){
        setBackground(Color.GRAY);
        addMouseListener(this);
        addMouseMotionListener(this);
    
        ColorButton red = new ColorButton("r", Color.RED);
        ColorButton blue = new ColorButton("b", Color.BLUE);
        ColorButton green = new ColorButton("g", Color.GREEN);

        red.addActionListener((e) -> {color = red.color;});
        blue.addActionListener((e) -> {color = blue.color;});
        green.addActionListener((e) -> {color = green.color;});

        add(red);
        add(blue);
        add(green);
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for(int i = 0; i < lines.size(); i++)
            lines.get(i).draw(g);
    }
    int mouseButton = -1;
    public void mousePressed(MouseEvent e) {
        mouseButton = e.getButton();
        if(e.getButton() == MouseEvent.BUTTON1)
            lines.add(new MyLine(e.getX(),e.getY(), e.getX(),e.getY(),color));
    }
    public void mouseReleased(MouseEvent e) {
        repaint();
        mouseButton = -1;
    }
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    public void mouseDragged(MouseEvent e) {
        if(mouseButton == MouseEvent.BUTTON1){
            lines.get(lines.size() - 1).setEncPosition(e.getX(),e.getY());
            repaint();
        }
        
    }
    public void mouseMoved(MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {}
}

class MyPanelCur extends JPanel implements MouseListener, MouseMotionListener{

    private class MyCurve{
        ArrayList<Point> pts = new ArrayList<>();
        Color color;
        MyCurve(){
            color = new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
        }
        void draw(Graphics g){
            // 점그리기
            // Iterator<Point> it = pts.iterator();
            // while(it.hasNext()){
            //     Point p = it.next();
            //     g.fillOval(p.x-1, p.y-1, 3, 3);
            // }
            g.setColor(color);
            for(int i = 0; i < pts.size()-1 ; i++){
                Point p1 = pts.get(i);
                Point p2 = pts.get(i+1);
                g.drawLine(p1.x, p1.y, p2.x, p2.y);
            }
        }
        void addPoint(int _x,int _y){
            pts.add(new Point(_x,_y));
        }
    }
    ArrayList<MyCurve> curves = new ArrayList<>();
    MyPanelCur(){
        addMouseListener(this);
        addMouseMotionListener(this);
        setBackground(Color.LIGHT_GRAY);
    }
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        for(int i= 0;i<curves.size();i++)
            curves.get(i).draw(g);
    }
    public void mousePressed(MouseEvent e) {
        MyCurve c = new MyCurve();
        c.addPoint(e.getX(), e.getY());
        curves.add(c);
        repaint();
    }
    public void mouseReleased(MouseEvent e) {
        MyCurve c = curves.get(curves.size()-1);
        c.addPoint(e.getX(), e.getY());
        repaint();
    }
    public void mouseDragged(MouseEvent e) {
        MyCurve c = curves.get(curves.size()-1);
        c.addPoint(e.getX(), e.getY());
        repaint();
    }
    public void mouseMoved(MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
}

public class My extends JFrame{
    My(){
        setSize(1000,500);
        setTitle("Title");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new GridLayout(1,2));

        add(new MyPanel());
        add(new MyPanelCur());

        setVisible(true);
    }
    public static void main(String[] args){
        new My();
    } 
}

태그: ,

카테고리:

업데이트:

댓글남기기