[JAVA] GUI 스윙

MINJEE·2024년 1월 14일

SMHRD_8_Java

목록 보기
9/10
post-thumbnail
  • GUI : 사용자가 편리하게 입출력 할 수 있도록 그래픽으로 화면을 구성하고, 마우스/키보드로 입력 받을 수 있도록 지원하는 사용자 인터페이스
  • AWT와 Swing 패키지 : 강력한 GUI 컴포넌트 제공
    • AWT 패키지 : AWT컴포넌트는 중량 컴포넌트, OS에 의해 그려지며, OS의 자원을 많이 소모하고 부담을 줌, 속도는 빠름
    • Swing 패키지 : AWT 기능 + 풍부하고 화려한 고급 컴포넌트 (AWT컴포넌트 이름 앞에 J자를 덧붙임), Swing 컴포넌트는 경량 컴포넌트, OS의 도움 없이 직접 그리므로 OS에 부담주지 않음

🔷 컨테이너와 컴포넌트 관계

  • 컨테이너 : 다른 컴포넌트를 포함할 수 있는 GUI 컴포넌트
    • 다른 컨테이너에 포함될 수 있음
    • Swing 컨테이너 : JPanel, JFrame, JApplet, JDialog, JWindow
    • 최상위 컨테이너 : 다른 컨테이너에 포함되지 않고도 화면에 출력되어 독립적으로 존재 가능한 컨테이너 (JFrame, JDialog, JApplet)
  • 컴포넌트 : 컨테이너에 포함되어야 화면에 출력될 수 있는 GUI 객체
    • 다른 컴포넌트를 포함 불가능, 순수 컴포넌트

최상위 컨테이너를 바닥에 깔고, 그 위에 컨테이너를 놓고, 다시 컴포넌트를 쌓아가는 방식 ⇒ 레고 블록 쌓는 듯이 GUI 프로그램 작성


🔷 Window Builder 설치

  • Window Builder : GUI 프로그램을 쉽게 할 수 있도록 도와주는 플러그인
  • 순서
    1. Eclipse의 메뉴바 → Help → Install New Software 클릭 → Add 클릭
    2. WindowBuilder | Download | The Eclipse Foundation
      Legacy Update Sites 부분의 Current버전의 link 클릭하여 나온 새로운 페이지의 url 복사
    3. Location부분에 복사한 url을 붙여넣기 하고, Name은 원하는 걸로 입력(Swing으로 해도 좋구) → Add 클릭 → 가운데 부분 모두 체크 후, Next 클릭 → Install Details창 Next 클릭 → Review Licenses창 동의 체크 후 Finish 클릭 (이클립스 오른쪽 하단에 설치 진행 상황 표시)
    4. 보통은 재시작하면 awt와 swing 패키지 사용 가능
      But, 안될 때는 밑에 실행
      • java.awt와 java.swing을 사용하기 위해서는 java.se모듈 인 java.desktop(java.awt, java.swin)과 java.sql(java.sql, javax.sql)을 따로 등록!
      • 프로젝트 폴더의 src폴더에 있는 module-info.java 안에 코드 작성

🔷 스윙 GUI 프로그램 만들기

스윙 프레임 만들기 → main() 메소드 작성 → 스윙 프레임에 스윙 컴포넌트 붙이기

  • 스윙 프레임(JFrame) : 모든 스윙 컴포너틑 담는 최상위 컨테이너
    • 구성 : 프레임, 메뉴바, 컨텐트 팬(컴포넌트들이 부착되는 공간)

    • JFrame 클래스를 상속받은 클래스 작성

    • 프레임 크기 반드시 지정(setSize()), 프레임을 화면에 출력하는 코드 반드시 필요(setVisible(true))

      public class 클래스명 extends JFrame {
      		public 클래스명() {
      				setTitle("타이틀"); //타이틀 (또는 super("타이틀");)
      				setSize(가로길이,세로길이); //프레임 크기
      				setVisible(true); //프레임을 화면에 출력
      				setDefaultCloseOperaion(JFrame.EXIT_ON_CLOSE); //닫기버튼 누르면 프로그램도 종료
      
      				Container 컨텐트팬변수 = getContenPane(); //프레임에 붙은 디폴트 컨텐트팬 알아내기
      				컨텐트팬변수.setBackground(Color.ORANGE); //배경색(오렌지)
      				컨텐트팬변수.setLayout(new FlowLayout()); //컨텐트팬에 FlowLayout 배치관리자로 설정	
      				JButton 버튼변수 = new JButton("표시글씨"); //버튼 컴포넌트 생성
      				컨텐트팬변수.add(버튼변수); //컨텐트팬에 버튼부착
      				컨텐트팬변수.add(new JButton("표시글씨2"); //버튼 컴포넌트 생성하여 컨텐트팬에 부착 
      		}
      
      		public static void main(String[] args){
      				클래스명 변수명 = new 클래스명(); //스윙 프레임 생성
      		}
      }
  • main() 기능은 최소화하기 (스윙 프로그램이 실행되는 시작점으로서의 기능만 작성하기!!)
  • 프레임에 컴포넌트 붙이기
    • 컨텐트팬 알아내서 컴포넌트 붙이기
    • Container 컨텐트팬변수 = getContenPane(); : 프레임에 붙은 디폴트 컨텐트 팬 알아내기
    • 컨텐트팬변수.setBackground(Color.색깔); : 컨텐트 팬 배경색 지정
    • 컨텐트팬변수.add(컴포넌트변수); : 컨텐트 팬에 컴포넌트 붙이기
  • 스윙 응용프로그램 종료
    • System.exit(0); : 응용프로그램 내에서 스스로 종료 (언제 어디서나 무조건 종료)
    • 프레임의 종료버튼(x) 클릭 : 화면에서 보이지 않게 프레임 윈도우 닫음, But 응용프로그램 종료x
    • frame.setDefaultCloseOperaion(JFrame.EXIT_ON_CLOSE); : 프레임 종료버튼 클릭 시 프레임과 응용프로그램 종료

🔷 배치관리자

: 컨테이너에 부착되는 컴포넌트의 위치와 크기 결정
  • 컨테이너마다 하나의 배치관리자 존재
  • 컨테이너 크기 변경 시, 컴포넌트 위치/크기 재결정
  • 대표 유형 : FlowLayout, BorderLayout, GridLayout, CardLayout
    • FlowLayout : 컴포넌트를 순서대로 왼→오 배치, 공간 없으면 아래로 내려와서 반복
    • BorderLayout : 컨테이너 공간을 5개 영역(동/서/남/북/중앙)으로 나눠서 응용프로그램에서 지정한 영역에 컴포넌트 배치
    • GridLayout : 컨테이너를 2차원 격자로 나눠서 컴포넌트를 순서대로 좌→우, 위→아래로 배치
    • CardLayout : 카드를 쌓아 놓은 듯이 컴포넌트를 포개어 배치
  • 디폴트 배치관리자 : 컨테이너 생성 시, 자동으로 생성되는 배치관리자
    • Window, JWindow, Frame, JFrame, Dialog, JDialog → BorderLayout
    • Panel, JPanel, Applet, JApplet → FlowLayout
  • 컨테이너변수.setLayout(new 배치관리자유형()); : 컨테이너에 배로운 배치관리자 설정
    • ex. JPanel p = new JPanel(); p.setLayout(new BorderLayout()); : JPanel에 BorderLayout 설정

🔹 FlowLayout 생성자

: FlowLayout() , FlowLayout(align, hGap, vGap)

  • align : 컴포넌트 정렬 방법
    • 왼쪽 정렬(FlowLayout.LEFT)
    • 오른쪽 정렬(FlowLayout.RIGHT)
    • 중앙 정렬(FlowLayout.CENTER, 디폴트)
  • hGap : 좌우 컴포넌트 사이 수평 간격(디폴트 5픽셀)
  • vGap : 상하 컴포넌트 사이 수직 간격(디폴트 5픽셀)

🔹 BorderLayout 생성자

: BorderLayout() , BorderLayout(hGap, vGap)

  • 배치관리자 설정 후, 컴포넌트 추가 방법 : 컨테이너변수.add(컴포넌트, index); (컴포너트를 index위치에 배치)
  • hGap : 좌우 컴포넌트 사이 수평 간격(디폴트 0픽셀)
  • vGap : 상하 컴포넌트 사이 수직 간격(디폴트 0픽셀)
  • index : 컴포넌트 위치
    • BorderLayout.NORTH
    • BorderLayout.EAST
    • BorderLayout.WEST
    • BorderLayout.SOUTH
    • BorderLayout.CENTER

🔹 GridLayout 생성자

: GridLayout() , GridLayout(rows, cols) , GridLayout(rows, cols, hGap, vGap)

  • rows : 격자 행수 (디폴트 1)
  • cols : 격자 열수 (디폴트 1)
  • hGap : 좌우 컴포넌트 사이 수평 간격 (디폴트 0픽셀)
  • vGap : 상하 컴포넌트 사이 수직 간격(디폴트 0픽셀)

🔹 배치관리자 제거

  • 컨테이너변수.setLayout(null);
  • 배치관리자가 없어지면, 컴포넌트에 대한 어떤 배치도 없음 (즉, 화면에 안 보임)
  • 응용프로그램에서 직접 컴포넌트의 크기/위치를 결정하고자 할 때 사용
  • 시간/마우스/키보드입력 등에 따라 컴포넌트 크기/위치 수시로 변하거나 여러 컴포넌트들이 서로 겹쳐 출력하고자 하는 경우에도 사용
  • 컴포넌트 삽입 시, 컴포넌트의 절대 위치/크기 설정
    • 컴포넌트변수.setSize(width, height) : 크기 설정
    • 컴포넌트변수.setLocation(x, y) : 위치 설정
    • 컴포넌트변수.setBounds(x, y, width, height) : 위치와 크기 동시 설정

🔷 이벤트 리스너

: 이벤트를 처리하는 자바 프로그램 코드
  • 이벤트 기반 프로그래밍 : 이벤트 발생에 의해 프로그램 흐름 결정되는 방식

    • 이벤트 종류 : 사용자 입력(마우스,키보드), 센서로부터 입력, 네트워크로부터 데이터 송수신, 다른 응용프로그램/스레드로부터의 메시지
    • 이벤트 처리 과정 : 이벤트 발생 → 이벤트 객체 생성 → 응용프로그램에 작성된 이벤트리스너 찾아서 실행
  • 이벤트 객체 : 발생한 이벤트에 관한 정보를 가진 객체

    • 이벤트객체.getSource() : 발생한 이벤트 소스 컴포넌트 리턴
      이벤트 객체이벤트 소스이벤트 발생하는 경우
      ActionEventJButton마우스/키
      JMenuItem메뉴 아이템 선택
      JTextField텍스트 입력 중 키
      ItemEventJCheckBox체크박스 선택/해제
      JRadioButton라디오버튼 선택 상태 변경
      JCheckBoxMenuItem체크박스 메뉴 아이템 선택/해제
      ListSelectionEventJList리스트에 선택된 아이템 변경
      KeyEventComponent키 누르기/떼기
      MouseEventComponent마우스 누르기/떼기/올리기/내려가기/드래그/움직이기
      FocusEventComponent포커스 받기/잃기
      WindowEventWindow윈도우 활성화/비활성화/아이콘화, 아이콘에서 복구, 열기/닫기/종료
      ComponentEventComponent컴포넌트 사라지기/나타나기/이동/크기변경
      ContainerEventContainer컴포넌트 추가/삭제
  • 이벤트 리스너는 클래스로 작성 (리스터 인터페이스를 상속받아 구현)

    // 1. 이벤트 리스너 클래스 작성 (리스너인터페이스 에 속한 추상메소드 모두 구현!!)
    class 리스너클래스명 implements 리스너인터페이스 {
    		public void 추상메소드명(이벤트객체 e) {
    				구현코드
    		}
    }
    
    // 2. 작성한 이벤트 리스너 등록
    리스너클래스명 리스너변수 = new 리스너클래스명();
    컴포넌트변수.add리스너인터페이스(리스너변수);
    리스너 인터페이스대응하는 어댑터추상 메소드메소드 호출되는 경우
    ActionListener없음actionPerforemed(ActionEvent)Action이벤트 발생
    ItemListener없음itemStateChanged(ItemEvent)Item이벤트 발생
    KeyListenerKeyAdapterkeyPressed(KeyEvent)키가 눌러질 때
    keyReleased(KeyEvent)키가 떼어질 때
    keyTyped(KeyEvent)유니코드 키 입력될 때
    MouseListenerMouseAdaptermousePressed(MouseEvent)마우스 버튼 눌러질 때
    mouseReleased(MouseEvent)마우스 버튼 떼어질 때
    mouseClicked(MouseEvent)마우스 버튼 클릭될 때
    mouseEntered(MouseEvent)마우스가 컴포넌트 위에 올라올 때
    mouseExited(MouseEvent)마우스가 컴포넌트를 벗어날 때
    MouseMotionListenerMouseAdaptermouseDragged(MouseEvent)마우스를 컴포넌트 위에서 드래그할 때
    mouseMoved(MouseEvent)마우스를 컴포넌트 위에서 움질일 때
    FocusListenerFocusAdqpterfocusGained(FocusEvent)컴포넌트가 포커스 받을 때
    focusLost(FocusEvent)컴포넌트가 포커스를 잃을 때
    WindowListenerWindowAdapterwindowOpened(WindowEvent)윈도우 생성되어 처음 보일 때
    windowClosing(WindowEvent)윈도우 닫기 시도할 때
    windowIconfied(WindowEvent)윈도우가 아이콘화될 때
    windowDeiconfied(WindowEvent)아이콘에서 원래 상태로 복귀할 때
    windowClosed(WindowEvent)윈도우가 닫혔을 때
    windowActivated(WindowEvent)윈도우가 활성화될 때
    windowDeactivated(WindowEvent)윈도우가 비활성화될 때
    ListSelectionListener없음valueChanged(ListSelectionEvent)list에 선택된 아이템이 변경될 때
    • 작성 방법 : 독립/내부/익명 클래스로 작성
      1. 독립 클래스로 작성 : 이벤트 리스너를 완전한 클래스로 작성 (여러 곳에서 사용할 때 적합)

        public class IndepClass extends JFrame {
        		public IndepClass() {
        				setTitle("Action이벤트리스너 독립 클래스");
        				setDefaultCloseOperaion(JFrame.EXIT_ON_CLOSE);
        
        				Container c = getContentPane();
        				JBtton btn = new JButton("Action");
        				btn.addActionListener(new 리스너클래스명()); //ActionListener 등록
        				c.add(btn);
        
        				setSize(250,120);
        				setVisible(true);
        		}
        		public static void main(String[] args) {
        				new IndepClass();
        		}
        }
        
        //독립 클래스로 이벤트 리스너 작성
        class 리스너클래스명 implements ActionListener { //ActionListener의 메소드 구현
        		public void actionPerformed(ActionEvent e) {
        				JButton b = (JButton)e.getSource();
        				if (b.getText().equals("Action")) b.setText("액션");
        				else b.setText("Action");
        		}
        }
      2. 내부 클래스로 작성 : 클래스 안에 멤버처럼 클래스 작성 (특정 클래스에서만 사용할 때 적합)

        public class InnerClass extends JFrame {
        		public InnerClass() {
        				setTitle("Action이벤트리스너 내부 클래스");
        				setDefaultCloseOperaion(JFrame.EXIT_ON_CLOSE);
        
        				Container c = getContentPane();
        				JBtton btn = new JButton("Action");
        				btn.addActionListener(new 리스너클래스명()); //ActionListener 등록
        				c.add(btn);
        
        				setSize(250,120);
        				setVisible(true);
        		}
        		//내부 클래스로 이벤트 리스너 작성
        		private class 리스너클래스명 implements ActionListener {
        				public void actionPerformed(ActionEvent e) {
        						JButton b = (JButton)e.getSource();
        						if (b.getText().equals("Action")) b.setText("액션");
        						else b.setText("Action");
        						
        						InnerClass.this.setTitle(b.getText());
        				}
        		public static void main(String[] args) {
        				new InnerClass();
        		}
        }
        • 클래스명.this 로 이벤트 리스너를 등록한 클래스 멤버에 대한 접근 용이
      3. 익명 클래스로 작성 : 클래스의 이름 없이 간단히 작성(간단한 리스너이면 익명 클래스 사용 추천)

        public class AnonymousClass extends JFrame {
        		public AnonymousClass() {
        				setTitle("Action이벤트리스너 내부 클래스");
        				setDefaultCloseOperaion(JFrame.EXIT_ON_CLOSE);
        
        				Container c = getContentPane();
        				JBtton btn = new JButton("Action");
        				//익명 클래스로 이벤트 리스너 작성 (이벤트리스너클래스명 없음. 등록하면서 그 안에 작성)
        				btn.addActionListener(new ActionListener(){
        						public void actionPerformed(ActionEvent e) {
        								JButton b = (JButton)e.getSource();
        								if (b.getText().equals("Action")) b.setText("액션");
        								else b.setText("Action");
        								
        								setTitle(b.getText());
        						}
        				}); //ActionListener 등록 + 구현
        				//람다식 이벤트 리스너 작성(메소드가 한개인 경우만 가능)
        				btn.addActionListener((ActionEvent e) -> {
        						JButton b = (JButton)e.getSource();
        						if (b.getText().equals("Action")) b.setText("액션");
        						else b.setText("Action");
        				});
        
        				c.add(btn);
        
        				setSize(250,120);
        				setVisible(true);
        		}
        		public static void main(String[] args) {
        				new AnonymousClass();
        		}
        }
        • 람다식 : 메소드가 하나인 인터페이스를 함수형 언어처럼 메소드를 매개변수로 사용하는 것처럼 사용
          (특징 : 타입(ex. ActionEvent) 생략 가능, 소괄호 생략 가능, 구현할 코드가 1줄이면 중괄호 생략 가능)
          (ActionEvent e) → { e.setText("액션"); }
          (e) → { e.setText("액션"); }
          e → e.setText("액션");
          [JAVA] 람다식 (Lambda Expression)
    • 어댑터 클래스 : 이벤트 리스너 인터페이스의 모든 메소드를 단순 리턴하도록 만든 클래스
      • 추상 메소드가 1개뿐인 이벤트 리스너는 어댑터 없음

      • 이벤트 리스너 인터페이스의 메소드 중 모두 구현하지 않고 몇 개 메소드만 구현하고 싶을 때 사용!

        class 리스너클래스명 implements MouseListener { //모든 메소드 구현해야 함!
        		public void mousePressed(MouseEvent e) { //사용하는 메소드
        				구현할 메소드
        		}
        		public void mouseReleased(MouseEvent e) {} //사용하지 않는 메소드들
        		public void mouseClicked(MouseEvent e) {}
        		public void mouseEntered(MouseEvent e) {}
        		public void mouseExited(MouseEvent e) {}
        }
        
        class 리스너클래스명 extends MouseAdapter { //사용하는 메소드만 구현
        		public void mousePressed(MouseEvent e) { 
        				구현할 메소드
        		}
        }
profile
개발, 분석 배운 내용 정리하기!

0개의 댓글