Java/프로젝트

자바 공굴리기3

Danny.Song 2020. 12. 29. 16:57

12-29 액션 리스너 버튼달기

 

---------------------------------------------수정 전-----------------------------------------------

ActionListener

 

버튼 추가한 공굴리기

 

 

코드

Ball.java

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
package rollingBall;
 
import java.util.Random;
 
public class Ball {
    private int         BallPosX;
    private int         BallPosY;
    
    private boolean     isRight;
    private boolean     isUp;
    
    
    public Ball() {
        Random r = new Random();
        this.BallPosX = 1 + r.nextInt(Core.WIDTH-5);
        this.BallPosY = 1 + r.nextInt(Core.HEIGHT-5);
    }
 
 
    public int getBallPosX() {
        return BallPosX;
    }
 
 
    public void setBallPosX(int ballPosX) {
        BallPosX = ballPosX;
    }
 
 
    public int getBallPosY() {
        return BallPosY;
    }
 
 
    public void setBallPosY(int ballPosY) {
        BallPosY = ballPosY;
    }
 
 
    public boolean isRight() {
        return isRight;
    }
 
 
    public void setRight(boolean isRight) {
        this.isRight = isRight;
    }
 
 
    public boolean isUp() {
        return isUp;
    }
 
 
    public void setUp(boolean isUp) {
        this.isUp = isUp;
    }
 
}
 
cs

 

Core.java

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
package rollingBall;
 
import java.awt.event.ActionListener;
 
public class Core {
    private Ball            ball;
    private View             view;
    private Listener        listener;
    private boolean         isPlay;
 
    public static final int WIDTH = 780;
    public static final int HEIGHT = 480;
 
    public Core() {
        
        ball = new Ball();
        view = new View();
        listener = view.getListener();
        listener.setCore(this);
                
        this.start();
    }
 
    private void start() {
        while(true) {
            
                this.move();
                reflect();
                draw();
                
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
        }
    }
 
    
    private void move() {
            if(isPlay) {
                if(ball.isRight())
                    ball.setBallPosX(ball.getBallPosX() + 1);
                else
                    ball.setBallPosX(ball.getBallPosX() - 1);
                
                
                if(ball.isUp())
                    ball.setBallPosY(ball.getBallPosY() + 1);
                else
                    ball.setBallPosY(ball.getBallPosY() - 1);
            }else {}        
    }
 
    private void reflect() {
        if(ball.getBallPosX() - 10 <=0 || ball.getBallPosX() + 10>= WIDTH)
            ball.setRight(!ball.isRight());
        if(ball.getBallPosY() - 10 <=0 || ball.getBallPosY() + 10>= HEIGHT)
            ball.setUp(!ball.isUp());
    }
 
    
    private void draw() {
        view.setPosXY(ball.getBallPosX(), ball.getBallPosY());
        view.draw();
    }
 
    public void clickedPlay() {
        this.isPlay = true;
    }
    
    public void clickedStop() {
        this.isPlay = false;
    }
 
    
    public static void main(String[] args) {
        new Core();
    }
        
}
 
cs

 

DrawComponent.java

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
package rollingBall;
 
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
 
import javax.swing.JComponent;
 
public class DrawComponent extends JComponent {
    
    private int posX;
    private int posY;
    
    
    public Dimension getPreferredSize() {
        return new Dimension(Core.WIDTH,Core.HEIGHT);
    }
    
    @Override
    public void paint(Graphics g) {
    
        g.setColor(Color.BLACK);
        g.fillRect(00, Core.WIDTH, Core.HEIGHT);
        
        g.setColor(Color.WHITE);
        g.fillOval(posX-10, posY-102020);
    }
 
    
    public void setPosXY(int posX, int posY) {
        this.posX = posX;
        this.posY = posY;
    }
    
    
    
    
}
 
cs

 

Listener.java

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
package rollingBall;
 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
public class Listener implements ActionListener {//버튼을 통해 들어오는 정보를 가공
    
    private Core core;
 
    @Override
    public void actionPerformed(ActionEvent e) {
        String actionCommand = e.getActionCommand();
 
        if(actionCommand == "play") {
            core.clickedPlay();    
        }
        
        else if(actionCommand == "stop") {
            core.clickedStop();
        }            
    }
    
 
    public void setCore(Core core) {
        this.core = core;
    }
    
}
 
cs

 

View.java

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
package rollingBall;
 
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
 
public class View extends JFrame{
    
    private JFrame                frame;
    private DrawComponent         comp;
    private JButton                button;
    private JButton             button2;
    private JPanel                 panel;
    private FlowLayout            flowLayout;
    private Listener            listener;
 
    public View() {
        frame = new JFrame("공 굴리기");
        comp = new DrawComponent();
        panel = new JPanel();
        flowLayout = new FlowLayout();
        button = new JButton("play");
        button2 = new JButton("stop");
        listener = new Listener();
        
        initButton();
        initPanel();
        initFrame();    
    }
    
    private void initButton() {
        button.setVerticalTextPosition(AbstractButton.CENTER);
        button.setHorizontalTextPosition(AbstractButton.LEADING);
        button.addActionListener(listener);
        button2.setVerticalTextPosition(AbstractButton.CENTER);
        button2.setHorizontalTextPosition(AbstractButton.LEADING);
        button2.addActionListener(listener);
    }
 
    private void initPanel() {
        panel.setLayout(flowLayout);
        panel.add(comp,flowLayout);
        panel.add(button,flowLayout);
        panel.add(button2,flowLayout);
    }
    
    private void initFrame() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }
 
    public void draw() {
        frame.repaint();
    }
 
    public void setPosXY(int posX, int posY) {
        comp.setPosXY(posX, posY);
    }
 
    public Listener getListener() {
        return listener;
    }
 
}
 
cs

 

 

 

------------------------------------------수정 후 -----------------------------------------------------------------

 

 

ButtonActionListener.java

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
package rollingBall;
 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
public class ButtonActionListener implements ActionListener {//버튼을 통해 들어오는 정보를 가공
    
    private Core core;
 
    @Override
    public void actionPerformed(ActionEvent e) {
        
        String actionCommand = e.getActionCommand();
        
        if(actionCommand == "play") {
            core.clickedPlay();    
        }
        
        else if(actionCommand == "stop") {
            core.clickedStop();
        }            
    }
    
    public void setCore(Core core) {
        this.core = core;
    }
    
}
 
cs

 

 

Core.java

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
package rollingBall;
 
import java.awt.event.ActionListener;
 
public class Core {
    private Ball                        ball;
    private View                         view;
    private ButtonActionListener        listener;
    private boolean                     isPlay;
 
    public static final int WIDTH = 780;
    public static final int HEIGHT = 480;
    
    public Core() {
        
        ball = new Ball();
        view = new View();
        listener = new ButtonActionListener();
        
        this.setObject();
        this.start();
    }
 
    private void setObject() {
        listener.setCore(this);
        view.informListener(listener);    
    }
 
    private void start() {
        while(true) {
            
                this.move();
                reflect();
                setPosXY();
                draw();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
        }
    }
 
    
    private void move() {
            if(isPlay) {
                if(ball.isRight())
                    ball.setBallPosX(ball.getBallPosX() + 1);
                else
                    ball.setBallPosX(ball.getBallPosX() - 1);
                
                
                if(ball.isUp())
                    ball.setBallPosY(ball.getBallPosY() + 1);
                else
                    ball.setBallPosY(ball.getBallPosY() - 1);
            }else {}        
    }
 
    private void reflect() {
        if(ball.getBallPosX() - 10 <=0 || ball.getBallPosX() + 10>= WIDTH)
            ball.setRight(!ball.isRight());
        if(ball.getBallPosY() - 10 <=0 || ball.getBallPosY() + 10>= HEIGHT)
            ball.setUp(!ball.isUp());
    }
 
    private void draw() {
        view.draw();
    }
 
    private void setPosXY() {
        view.setPosXY(ball.getBallPosX(), ball.getBallPosY());
    }
    
    public void clickedPlay() {
        this.isPlay = true;
    }
    
    public void clickedStop() {
        this.isPlay = false;
    }
    
    public static void main(String[] args) {
        new Core();
    }
        
}
 
cs

 

 

View.java

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
package rollingBall;
 
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
 
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
 
public class View extends JFrame{
    
    private JFrame                frame;
    private DrawComponent         comp;
    private JButton                button;
    private JButton             button2;
    private JPanel                 panel;
    private FlowLayout            flowLayout;
 
    public View() {
        frame = new JFrame("공 굴리기");
        comp = new DrawComponent();
        panel = new JPanel();
        flowLayout = new FlowLayout();
    
        initButton();
        initPanel();
        initFrame();    
    }
    
    private void initButton() {
        button = new JButton("play");
        button2 = new JButton("stop");
 
        button.setVerticalTextPosition(AbstractButton.CENTER);
        button.setHorizontalTextPosition(AbstractButton.LEADING);
        button2.setVerticalTextPosition(AbstractButton.CENTER);
        button2.setHorizontalTextPosition(AbstractButton.LEADING);
    }
 
    private void initPanel() {
        panel.setLayout(flowLayout);
        panel.add(comp,flowLayout);
        panel.add(button,flowLayout);
        panel.add(button2,flowLayout);
        
    }
    
    private void initFrame() {
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.pack();
        frame.setVisible(true);
    }
 
    private void registerListener(ButtonActionListener listener) {
        button.addActionListener(listener);
        button2.addActionListener(listener);
    }
    
    public void draw() {
        frame.repaint();
    }
 
    public void setPosXY(int posX, int posY) {
        comp.setPosXY(posX, posY);
    }
 
    
    public void informListener(ButtonActionListener listener) {
        registerListener(listener);
    }
 
}
 
cs

 

성찰

Listener 클래스를 처음에 Router라는 이름으로 만들었다. 클래스명으로 클래스의 역할을 알 수 있어야 한다.

Router 클래스에서 isPlay라는 boolean 변수를 static으로 만들었었다. 

static은 객체 지향적이지 않다.

static을 사용할 경우 데이터가 객체(확장 기능, 정보 숨기기 등) 캡슐화된다는 원칙을 위반한다.

static은 절차적 프로그래밍 특성이다. 객체 지향 프로그래밍의 특성이 아니다.

 

 

버튼을 추가해서 Play와 Stop기능을 만들었다.

처음 생각으로 뷰에서 버튼을 만들고 액션리스너를 통해서 정보를 컨트롤러로 넘겨준다고 생각했는데

내가 뷰를 만드는 사람의 입장이라면 액션리스너를 생각하면 안된다. 단지 사용자에게 보여줄 View만 만들어야 한다.

버튼에 액션리스너를 연결하면 끝이다.

 

이제 액션리스너가 실행 됐을 때 정보를 받아줄 클래스를 하나 만들고 정보를 가공해서 코어 클래스로 보내준다.

물론 뷰에서 정보를 바로 코어 클래스로 보내서 가공해도 되지만 나중에 큰 프로그램을 만들 때를 생각해서

항상 버튼을 기다리고 있는 Listener 클래스를 만들어서 data를 가공해서 Core 클래스로 넘겨준다.

 

 

-------------------수정 후-----------------

클래스명은 구체적이면 좋다.

메소드는 하나의 역할만 해야한다.

 

 

 

 

 

 

코드 설명

View 클래스에서 버튼에 액션 리스너를 달아준다. button.addActionListener(listener);

여기에 인자는 객체가 들어가는데 이 객체를 Core 클래스로 넘겨줘야 한다. 

Core 클래스에서 따로 listener = new Listener() 로 객체를 생성하면 서로 다른 listener객체가 만들어진다.

즉) view - listener - core로 data를 전달해야하는데

 

view - listener_1 - core

       - listener_2 - core

이렇게 다른 객체에 data를 전달해주기 때문에 실행이 되지 않는다.

 

 

+패널을 만들어서 레이아웃을 설정해주고 거기에 버튼을 추가한다.

그 패널을 프레임에 추가한다.

 

 

 

 

 

 

 

MVC 패턴

그림 출처 위키백과

<https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0 %EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC>