자바 Swing(스윙) - (2)

2022. 10. 6. 08:36Dev.Program/Java & Spring

728x90

지난시간에 했던 2단계까지는 별로 중요하지 않음! 앞으로 하는게 중요!

< 이벤트(Event) >

  • 컴포넌트(버튼 등)에서 사용자에 의해 어떤 상호작용이 일어나는 것

ex) 버튼 클릭, 라디오버튼 선택 등

  • 이벤트가 발생했을 때 어떤 동작을 수행하기 위해서는 컴포넌트와 이벤트 리스너를 서로 연결해야함

⇒ 컴포넌트 객체의 addXXXListener() 메서드를 호출하여 리스너 객체 전달

ex) btn.addActionListener(리스너 객체);

< 이벤트 처리(Event Handling) >

  • 컴포넌트에 특정 이벤트가 발생했을 때 수행할 동작을 지정하여 처리하는 것 
  • 리스너(Listener) 내에 수행할 동작을 명시

⇒ 주로 XXXListener 인터페이스 또는 XXXAdapter 클래스가 제공됨

  • 리스너 객체를 직접 구현하거나 별도의 핸들러 클래스를 사용하여 상속받아 구현 
  • 리스너 인터페이스는 주로 java.awt.event 패키지 내에 위치함 

 

======== JAVA0420

  • 지난 시간에 했던 event 그대로 src로 이동시키기(드래그)

======== Test_Stage_1.java 만들기

package event_handling;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Test_Stage_1 extends JFrame {

public Test_Stage_1() {
showFrame();
}

public void showFrame() {
setTitle("1단계 이벤트 처리");
setBounds(600, 400, 300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// JButton 컴포넌트 생성 및 부착
JButton btn = new JButton("버튼");
add(btn);

setVisible(true);
}

public static void main(String[] args) {
new Test_Stage_1();
}
}
  • 실행창

 

  • 클래스 밖에 만들기 & 빨간 밑줄 눌러서 Add~ 로 자동 추가해주기
@Override
public void actionPerformed(ActionEvent e) {
// 버튼 클릭 시 자동으로 호출되는 메서드
System.out.println("버튼 클릭!");
}
  • Add~ 로 추가 시 이렇게 자동으로 생성됨

 

// JButton 컴포넌트에 ActionListener 를 연결하여 이벤트 처리
// ⇒ addXXXListener() 메서드 호출
// 1단계. 리스너를 구현하는 서브클래스 사용
MyActionListener listener = new MyActionListener();
btn.addActionListener(listener);
  • showFrame(); 안에 추가해주기
  • 누를 때 마다 동작함!
    ⇒ ActionListener 인터페이스는 추상메서드가 1개이므로 ActionAdapter 가 없음



======== Ex_Stage_3.java (Ex_Stage_2.java 복사해서 만들기)

363 내부클래스

< 이벤트 처리 3단계 >

3단계. 내부클래스 형태로 정의

< Ex_Stage_3 class 내부 >

class MyInnerWindowAdapter extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
// 창 닫기 버튼 클릭 시 호출되는 메서드
System.out.println("windowClosing");
System.exit(0); // 프로그램 종료
}
}
  • 추가
  • 내부클래스에서는 외부클래스(Ex_Stage_3)의 멤버에 자유롭게 접근 가능
public void showFrame() {
setTitle("이벤트 처리 - 3단계");
setBounds(600, 400, 300, 200);

// 이벤트 처리 3단계. 내부 클래스 사용
MyInnerWindowAdapter listener = new MyInnerWindowAdapter();
addWindowListener(listener);

setVisible(true);
}
  • 이 부분만 수정!
  • 똑같이 동작 후 close 됨!

 

  • src 파일 → Ex_Stage_3.java 하나 있다

  • bin 파일 → 외부클래스명$내부클래스명.class 생성 되어있는 거 볼 수 있다

 

366p

======== Test_Stage_3.java 만들기(Test_Stage_1.java 복사)

  • 이 부분 중괄호 안으로 끌고 오기
  • 모바일에서는 이 작업을 많이 만날 거다! (웹에서는 크게 많지 않음)

 

======== Ex_Stage_4.java (Ex_Stage_3 복사)

365p

< 이벤트 처리 4단계 >

  • 익명 내부 클래스 형태로 정의

⇒ 리스너 인터페이스 또는 어댑터 클래스의 이름을 사용하여

변수선언 및 인스턴스 생성과 추상메서드 구현까지 동시에 수행하는 방법

⇒ 개발자가 별도의 이름을 부여하지 않으므로 이름이 없다는 뜻의 익명 클래스로 명명됨.

 

  • listener 는 이제 인스턴스 변수기 때문에 오류뜨는 위에 꺼 지워도 됨!
  • 오류 안남!
    ⇒ 익명 인스턴스 내부 클래스 형태로 정의되었으므로 다른 메서드에서도 접근 가능한 객체

 

이벤트 처리 4단계. 익명 내부 클래스 사용

⇒ 별도의 인스턴스 생성 없이 바로 익명클래스 타입 변수 사용

  • ⇒ 메서드 내에서 정의한 익명 로컬 내부 클래스이므로 다른 메서드에서는 접근이 불가능하고, 현재 메서드에서만 접근 가능한 객체

 

  • 이런식으로 접근할때는 자동완성으로 하기! {}; 가 익숙하지 않기 때문
  • 추상메서드를 자동으로 만들어준다!

 

WindowListener 인터페이스를 사용한 익명 내부 클래스

  • 변수 선언, 클래스 정의, 생성까지 한번에 가능!



======== Test_Stage_4.java (Test_Stage_3.java 복사)

> 4단계로 바꿔보기!

  • 4단계. 익명 인스턴스 내부 클래스 형태로 정의

 

  • 4단계. 익명의 로컬 내부클래스 사용

 

왜 listener 라고 변수에 저장해서 사용할까? - 매번 접근할 수 있기 때문에(재사용)

  • 근데 여기선 listener를 한 번만 사용함! 그럼 굳이 변수가 필요할까

⇒ 5단계로 넘어가보자!

  • 임시객체 : 재사용 불가

======== Ex_Stage_5.java (Ex_Stage_4.java 복사)

< 이벤트 처리 5단계 >

  • 익명 내부 클래스의 임시 객체 형태로 정의하여 사용

⇒ 익명 내부 클래스 형태는 동일하나 객체를 한 번 사용하고 끝낼 경우 객체의 주소를 저장하는 참조변수도 필요없으므로 객체가 필요한 파라미터에 객체 생성 코드를 바로 명시하는 것 ( 임시객체 : 재사용 불가 )

⇒ 동일한 객체를 사용해야할 경우 객체 생성 코드를 중복으로 작성해야함

package event_handling;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;

public class Ex_Stage_5 extends JFrame {

public Ex_Stage_5() {
showFrame();
}

public void showFrame() {
setTitle("이벤트 처리 - 5단계");
setBounds(600, 400, 300, 200);

// 이벤트 처리 5단계.
// 익명 내부 클래스의 임시 객체 형태로 정의하여 사용
// ⇒ 익명 내부클래스 형태는 동일하나

//    객체를 한 번 사용하고 끝낼 경우
//    객체의 주소를 저장하는 참조변수도 필요없으므로
//    객체가 필요한 파라미터에 객체 생성 코드를 바로 명시하는 것
addWindowListener(new WindowAdapter() {

@Override
public void windowClosing(WindowEvent e) {
System.out.println("windowClosing");
System.exit(0);
}

});

setVisible(true);
}

public static void main(String[] args) {
new Ex_Stage_5();
}

}
  • new 해서 자동완성 하기! (익명이라 Anonymous~)
  • 오버라이딩 추가
  • 완성!

→ 안드로이드 쓸 때는 이게 초반에 나옴….ㅎ

 

======== Test_Stage_5.java (Test_Stage_4.java 복사)

> 똑같이 만들어보기

package event_handling;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Test_Stage_5 extends JFrame {

public Test_Stage_5() {
showFrame();
}

public void showFrame() {
setTitle("5단계 이벤트 처리");
setBounds(600, 400, 300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// JButton 컴포넌트 생성 및 부착
JButton btn = new JButton("버튼");
add(btn);

// JButton 컴포넌트에 ActionListener 를 연결하여 이벤트 처리
btn.addActionListener(new ActionListener() {

@Override
public void actionPerformed(ActionEvent e) {
System.out.println("버튼 클릭!");
}
});

setVisible(true);
}

public static void main(String[] args) {
new Test_Stage_5();
}

}
  • 객체를 재사용할 때는 4단계 사용, 재사용하지 않을 때는 임시객체(1회용)를 사용하는 5단계 사용! (4,5단계, 그 중에서도 5단계를 가장 많이 사용! 특히 안드로이드에서!)

 

375p

====================================================================

  • 클래스 - 우클릭 - Open With - WindowBuilder Editor 있는지 확인
  • 눌러보면
    모양 바뀜
  • 아랫쪽 Design 탭 눌러보기 (이클립스 켜고 처음에는 좀 오래걸림)
  • 이 화면 나오면 됨! 사용 준비 완료!

====================================================================

 

======== Ex.java 만들기

 

import javax.swing.JFrame;

public class Ex extends JFrame {
public Ex() {
showFrame();
}

public void showFrame() {
setBounds(600, 400, 300, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setVisible(true);
}

public static void main(String[] args) {
new Ex();
}

}

  • Build 열기 (오른쪽 창 보임)
import javax.swing.JFrame;

public class Ex {
public Ex() {
showFrame();
}

public void showFrame() {
// JFrame f = new JFrame();
// f.setBounds(600, 400, 300, 200);
// f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// f.setVisible(true);
// setBounds(600, 400, 300, 200);
// setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// setVisible(true);
}

public static void main(String[] args) {
new Ex();
}

}



  • 바깥 선택됨

  • false 로 바꾸면 실행했을 때 사이즈 조절 안됨

  • 코드로 돌아가면 자동으로 붙어있다 (둘은 연동되어 있음)

 

  • 안쪽 선택됨



  • JButton 눌러보기
  • 여기에 마우스 갖다대면 바뀜! (클릭하면 그 위치에 붙는다!)
  • 누르면 버튼 생김
  • 다시 버튼 만들어보기
  • 또 생성됨
  • 코드로 돌아가보면 이렇게 자동으로 생성되어있다!

 

  • getContentPane() 눌러보기 → Layout 보기!
  • 우리가 상속받은 건 JFrame

⇒ JFrame 객체(프레임)의 기본 레이아웃(별도 설정 없으면 BorderLayout 적용됨)

< Ex.java >

이제 showFrame(); 빼고 전부 다 지우고 다시 기본으로!

  • 그리고 버튼 추가해보기!
  • 실행창
  • “center” 라는 글자는 뒤에 가려져서 안 보임

  • BorderLayout 을 통해서 위치를 지정해준다
  • 이제 각자 제 영역 찾아감!

 

  • 나머지도 추가해주기
  • 버튼 다섯 개 완성!

 

빌더로 가보기

  • North 의 properties 로 가서 constraints 눌러보기
  • 센터 누르면 이렇게 덮어씀

  • background
  • 실행하면 버튼 색 바뀜

  • 줄이고 늘리고 해도 크기만 변경될 뿐 버튼 각각의 위치는 변경되지 않는다. 



> 버튼 5개에 각각 ActionListener 를 연결하여 버튼 클릭 이벤트 처리

  • 5단계로 만들기 ( 5개의 버튼이 각자 이벤트가 다르기 때문! ⇒ 이름 출력하도록 )
  • 리스너 5번 호출
btnCenter.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("CENTER");
}
});
btnEast.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("EAST");
}
});
btnWest.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("WEST");
}
});
btnSouth.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
  System.out.println("SOUTH");
}
});
btnNorth.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("NORTH");
}
});
  • 누르면 이렇게 출력창에 이름 보임

 

> 4단계로 만들기 (버튼클릭! 이라는 동작만 하면 됨)

ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("버튼 클릭!");
}
};
btnCenter.addActionListener(listener);
btnEast.addActionListener(listener);
btnWest.addActionListener(listener);
btnSouth.addActionListener(listener);
btnNorth.addActionListener(listener);

setVisible(true);
  • 한 번만 만들고 돌려서 쓰기 때문에 코드가 훨씬 짧아짐!

 

======== Ex2.java (Ex.java 복사)

  • 기본 틀만 남기기!

 

JTextField ⇒ 스윙에서의 text 상자 (JTextArea 도 있음!)

  • int columns → 크기 정할 수 있음


JTextField : 텍스트 1줄 입력이 가능한 컴포넌트

// 텍스트 1줄 입력이 가능한 컴포넌트 : JTextField
JTextField tf = new JTextField();
// JTextField 컴포넌트 CENTER 영역에 부착
add(tf, BorderLayout.CENTER);

// OK 버튼 SOUTH 영역에 부착
JButton btnOk = new JButton("OK");
add(btnOk, BorderLayout.SOUTH);

// OK 버튼 리스너 연결 - 5단계
btnOk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {

}
});

 

btnOk.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// JTextField 컴포넌트에 입력된 텍스트 가져와서 출력
String str = tf.getText();
System.out.println("입력 데이터 : " + str);
}
});
  • 근데 입력 / 출력한 뒤에 텍스트 상자 안에 남아있는 오케이~~ 글자를 없애고 싶다!

> 입력 데이터 출력 후 텍스트필드 초기화

tf.setText("");
  • 한 줄 추가~!
  • 입력받고 텍스트 상자 안에 메세지 사라짐!



JLabel : 텍스트 1줄 출력이 가능한 컴포넌트

  • 이렇게 만들어도 된다

design 으로 가보기

  • 자동으로 만들기!
  • 자동 생성!

 

OK 버튼을 안 누르고, 엔터를 쳤을 때도 넘어가게 만들고 싶다!

tf.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {

System.out.println("JTextField 리스너 동작!");
}
});
  • 엔터 쳤을 때도 동작됨!
  • 엔터 쳤을 때 동작하게 하고 싶다면 이렇게 그냥 ActionListener 로 사용하면 됨

  • 최종
  • 이제 엔터 치면 내용물 초기화됨!

  • 우클릭
  • actionPerformed 눌러보기!
  • 5단계 자동으로 생성해줌



  • 텍스트 상자 우클릭
  • keyReleased
  • 자동완성 됨
  • 키 누르는 족족 전부 동작:)

 

  • 키 코드랑 키 char 타입 찍어보기!
  • 아스키 코드 값 나옴! (지금은 대소문자 구분 안됨)
  • shift 는 16 나오고… 지우면(백스페이스) 8 나오고 등등...
  • 이렇게 내가 뭐 눌렀는지 감지 됨 ( 이런걸로 해킹하고 그러는거…. )

 

  • key 안에서 오버라이딩 눌러보기 2개 더 있다!
  • pressed 는 누르는 동작 (떼기도 전에 동작 시키는거! release는 누르고 떼면 동작)
  • typed 는 눌렀다 떼는 동작


======== Ex3.java (Ex2.java 복사)

필수코드 빼고 지우기

> 마우스의 움직임을 감지하는 리스너 만들어보자

  • 우클릭하면 이렇게 마우스 리스너 3가지 보임 ( 각자 이벤트 다름 )
// 마우스 움직임을 감지하는 리스너 MouseListener
addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
System.out.println("mouseReleased");
}

@Override
public void mousePressed(MouseEvent e) {
System.out.println("mousePressed");
}

@Override
public void mouseExited(MouseEvent e) {
System.out.println("mouseExited");
}

@Override
public void mouseEntered(MouseEvent e) {
System.out.println("mouseEntered");
}

@Override
public void mouseClicked(MouseEvent e) {
System.out.println("mouseClicked");
}
});

 

  • 추가
addMouseMotionListener(new MouseMotionListener() {

@Override
public void mouseMoved(MouseEvent e) {
System.out.println("mouseMoved");
}

@Override
public void mouseDragged(MouseEvent e) {
System.out.println("mouseDragged");
}
});

 

  • 마우스 움직일 때마다 좌표 찍어보기!
  • 마우스 위치에 따라 좌표 변함




======== Ex4.java (Ex3.java 복사)

필수코드 빼고 다지우기

< JPanel >

  • 여러개의 컴포넌트를 부착할 수 있는 경량 컨테이너
  • 별도의 설정이 없을 경우 기본 레이아웃은 FlowLayout

⇒ 컴포넌트를 좌 → 우, 상 → 하 방향으로 자연스럽게 배치

( 프레임 크기가 변경되면 컴포넌트 크기는 유지되고, 배치 위치가 변경됨 )

  • 아직은 뭐가 다른지 모름!
  • Ex1.java 에서 버튼 5개 가져오기

  • p.add 로 바꾸고 위치 정보 지우기
  • 길게 늘이면 배치가 바뀜! (그러나 버튼 크기는 변경되지 않는다)

 

  • 버튼 두개 추가!
  • design 탭에 가면
    p와 panel 같은 선상에 있음
  • 이름이나 나이 따로 입력받을 때 이런게 필요하다…!





728x90

'Dev.Program > Java & Spring' 카테고리의 다른 글

자바 Swing(스윙) - (4)  (0) 2022.10.06
자바 Swing(스윙) - (3)  (0) 2022.10.06
DAO/DTO 패턴 / 자바 Swing(스윙) - (1)  (0) 2022.10.06
JDBC(Java DataBase Connectivity)  (0) 2022.10.06
예외(Exception) / 쓰레드(Thread)  (1) 2022.10.06