JAVA/GUI

[자바] 콜백(CallBack) - JFrame

yujin0517 2021. 7. 19. 17:14

콜백(CallBack)을 왜 사용하는가?

특정 조건이 있고, 이 조건을 만족할 때마다 기능을 수행한다고 하자.

콜백을 사용하면 이벤트가 발생하여 특정 조건을 만족시켰을 경우, 콜백 함수를 호출하여 바로 기능을 수행할 수 있다. 

콜백 함수는 바로바로 사용할 수 있으며, 조건이 맞는지 틀린지 확인하는 과정을 거치지 않아도 되기에 효율적이다.

만약, 콜백을 사용하지 않고 계속 객체에 접근하는 방식으로 코드를 작성하였다고 하자.

해당 객체에 어떠한 오류가 발생할 경우 그 객체부터 접근하는 과정까지 모두 수정이 필요할 수 있다.

콜백이라는 개념을 사용하면 객체의 주소만 연결시켜주면 바로 기능을 수행할 수 있다. 

 

* 이번 글에서는 수업 예제인 콜백을 GUI코드로 예시를 들고, 다음 글에서 GUI를 제외한 콜백 코드를 구현할 것입니다. 

 

연습하기

- CallBack interface 생성하기 

interface MyCallBack {  

	public void add();

	public void sub();
}

 

인터페이스를 생성하여 add, sub 추상 메소드를 선언한다. 이 메소드는 MyCallBack 인터페이스를 implements 하는 메소드에서 오버 라이딩되어 사용될 것입니다.

 

- MyPanel 클래스 생성하기

class MyPanel extends JPanel implements ActionListener {

	//버튼 선언하기
	JButton addBtn;
	JButton subBtn;
    
	//인터페이스의 주소값을 받기 위함
	MyCallBack callback;
	
	public MyPanel(MyCallBack callback) {
		//interface 
		this.callback = callback;
		
		// 버튼 객체 생성
		addBtn = new JButton("더하기 버튼");
		subBtn = new JButton("빼기 버튼");

		// 레이아웃 및 배경색 설정
		this.setLayout(new FlowLayout(FlowLayout.CENTER, 50, 50));
		this.setBackground(Color.BLUE);

		// 패널에 버튼 추가
		this.add(addBtn);
		this.add(subBtn);

		// 이벤트 리스너
		addBtn.addActionListener(this);
		subBtn.addActionListener(this);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		//다운캐스팅
		JButton button = (JButton) e.getSource();
        
		//버튼을 클릭할 경우, 일어나는 이벤트들
		if (button.getText().equals(addBtn.getText())) {
			System.out.println("더하기 버튼 클릭");
			callback.add();  //MyCallBack 인터페이스에 접근하여 add 메소드를 실행
		} else if (button.getText().equals(subBtn.getText())) {
			System.out.println("빼기 버튼 클릭");
			callback.sub();  //MyCallBack 인터페이스에 접근하여 sub 메소드를 실행
		}
	}

}// end of MyPanel

 

MyCallBack 인터페이스의 주소값을 사용하기 위해 인터페이스 타입으로 callback 변수를 선언합니다.

생성자에 MyCallBack을 타입으로 하는 callback변수를 넣어준 뒤, this 키워드를 사용해 자신의 객체를 호출합니다.

버튼과 패널의 옵션을 지정하고, 프레임에 추가하여 생성자에서 나머지 코드를 구현합니다. 

MyPaenl 메소드에서는 ActionListener 인터페이스를 implements 하였기에 actionPerformed 메소드를 오버 라이딩해야 합니다. 

* 자세한 코드 설명은 주석을 달아 설명해놓았습니다!

 

- MyFrame 클래스 생성하기 

class MyFrame extends JFrame implements MyCallBack {
	//label 선언
	JLabel label;
    
	//객체의 주소값을 받기 위함
	MyPanel myPanel;

	//생성자
	public MyFrame() {
		initData();
		setInitLayout();
	}

	//initData 메소드
	private void initData() {
		setTitle("Button Click Event");
		setSize(500, 500);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		label = new JLabel("Hello, ");

		//MyPanel 생성자에 MyCallBack 매개변수가 있기 때문에 this를 참조변수로 넣어줌
		//this를 사용해도 되는 이유 : MyFrame 클래스에서 MyCallBack을 implements 했기 때문.
		myPanel = new MyPanel(this);
        
		myPanel.setPreferredSize(new Dimension(500, 300));
	}// end of initDate

	//setInitLayout 메소드
	private void setInitLayout() {
		setVisible(true);
		setLayout(new BorderLayout());
		this.add(label, BorderLayout.NORTH);
		this.add(myPanel, BorderLayout.SOUTH);
	}// end of setInitLayout
	
	//오버라이딩
	@Override
	public void add() {
		label.setText("더하기 버튼 클릭, 화면에 표시됨!");
		//label에 접근하여 표시되는 텍스트를 변경
	}

	@Override
	public void sub() {
		label.setText("빼기 버튼 클릭, 화면에 표시됨!");
		//label에 접근하여 표시되는 텍스트를 변경
	}

}

 

MyFrame에 MyPanel을 추가하기 위해 MyPanel 타입으로 myPanel 변수를 선언한다.

initData 메소드에서 MyPanel의 객체 생성을 할 때, 참조 변수로 this를 넣어줬다. MyPanel의 생성자에 매개변수가 있기 때문에 참조 변수가 필요하며, MyFrame 클래스는 MyCallBack 인터페이스를 implements 하였기 때문에 this를 참조 변수로 넣어도 상관없다. 

오버 라이딩을 하여 인터페이스에서 선언한 추상 메서드를 재정의 한다. 

 

- 메인메소드 실행하기 

public class CallBackEX {
	public static void main(String[] args) {
		new MyFrame();
	}
}

 

* 위의 코드는 전부 한 클래스 안에서 클래스와 인터페이스를 선언하여 작성한 코드입니다. 

 

감사합니다!

 

2021.07.19

'JAVA > GUI' 카테고리의 다른 글

[자바] KeyListener + Scanner  (0) 2021.07.20
[자바] JFrame 이미지 추가하기 - 슈퍼마리오(1)  (0) 2021.07.17
[자바] KeyListener  (0) 2021.07.15
[자바] JPanel  (0) 2021.07.15
[자바] JButton 만들기 + 클릭 이벤트  (0) 2021.07.14