Java 기본적인 스윙 컴포넌트와 활용 - 1

1. 스윙 컴포넌트


스윙 프로그램으로 GUI 화면을 구성하는 방법은 두 가지이다.

  • 컴포넌트 기반 GUI 프로그래밍
    • 스윙 패키지에 주어진 GUI 컴포넌트를 이용하여 쉽게 작성할 수 있지만 자바 패키지에서 제공하는 GUI 컴포넌트의 한계
  • 그래픽 기반 GUI 프로그래밍
    • 선, 원 등의 도형과 이미지를 이용하여 그래픽으로 직접 화면에 그리기 가능, 독특한 GUI 구성 가능, 실행 속도가 빠름, 개발자에게 부담이 큼

위와 같은 이유로 혼합하여 GUI 응용프로그램을 작성한다.


스윙 컴포넌트의 공통 메서드

JComponent에는 모든 스윙 컴포넌트들이 상속받는 공통 메서드와 상수들이 작성되어 있기 때문에 GUI 프로그램을 작성하기 위해서는 이 메서드들을 알아둬야 한다.

  • 컴포넌트 모양과 관련된 메서드
    • void setForeground(Color) : 전경색(글자색) 설정
    • void setBackground(Color) : 배경색 설정
    • void setOpaque(boolean) : 불투명성 설정
    • void setFond(Font) : 폰트 설정
    • Font getFont(): 폰트 리턴
  • 컴포넌트 상태와 관련된 메서드
    • void setEnabled(boolean) : 컴포넌트 활성화/비활성화
    • void setVisible(boolean) : 컴포넌트 보이기/숨기기
    • boolean isVisible() : 컴포넌트의 보이는 상태 리턴
  • 컴포넌트의 위치와 크기에 관련된 메서드
    • int getWidth() : 폭 리턴
    • int getHeight() : 높이 리턴
    • int getX() : x좌표 리턴
    • int getY() : y좌표 리턴
    • Point getLocationOnScreen() : 스크린 좌표상에서 컴포넌트 좌표
    • void setLocation(int,int) : 위치 지정
    • void setSize(int,int) : 크기 지정
  • 컨테이너를 위한 메서드
    • Component add(component) : 자식 컴포넌트 추가
    • void remove(Component) : 자식 컴포넌트 제거
    • void removeAll() : 모든 자식 컴포넌트 제거
    • Component[] getComponents() : 자식 컴포넌트 배열 리턴
    • Container getParent() : 부모 컨테이너 리턴
    • Container getTopLevelAncestor() : 최상위 부모 컨테이너 리턴


2. JLabel


JLabel은 문자열이나 이미지를 스크린에 출력하는 레이블 컴포넌트를 만드는 클래스이다.

생성자

JLabel() // 빈 레이블
JLabel(Icon image) // 이미지 레이블, png,gif,jpg만 가능
JLabel(String text) // 문자열 레이블
JLabel(String text, Icon image, int hAlign) // 문자열과 이미지를 모두 가진 레이블

ImageIcon img = new ImageIcon("image\\sunset.jpg"); // 인자로 이미지 파일 경로
// 문자열과 이미지를 레이블 컴포넌트 영역 내에 중앙에 정렬
JLabel label = new JLabel("안녕하세요",image,SwingConstants.CENTER);
  • hAlign : 수평 정렬 값으로 아래 셋 중 하나
    • SwingConstants.LEFT
    • SwingConstants.RIGHT
    • SwingConstants.CENTER


3. JButton


JButton은 버튼 컴포넌트(간단한 버튼)을 만드는데 이용된다. 버튼을 마우스로 클릭하거나 키로 선택하면 Action 이벤트가 발생한다. 버튼 생성자는 다음과 같다.

JButton() // 빈 버튼
JButton(Icon image) // 이미지 버튼
JButton(String text) // 문자열 버튼
JButton(String text,Icon image) // 문자열과 이미지를 가진 버튼


이미지 버튼 만들기

JButton은 마우스 접근에 따라 모양이 다른 3개의 버튼 이미지를 출력할 수 있다. 버튼에는 작은 이미지가 사용되므로 주로 아이콘으로도 불린다.

  • normalIcon : 버튼이 보통 상태에 있을 때 출력되는 디폴트 이미지, 생성자나 JButton의 setIcon(Icon image)를 통해 설정
  • rolloverIcon : 버튼 위에 마우스가 올라갈 때 출력되는 이미지, JButton의 setRolloverIcon(Icon image)을 통해 설정
  • pressedIcon : 버튼이 눌러져 있을 동안 출력되는 이미지, JButton의 setPressedIcon(Icon image)을 통해 설정
// 먼저 이미지 생성
ImageIcon normalIcon = new ImageIcon("images/normalIcon.gif");
ImageIcon rolloverIcon = new ImageIcon("images/rolloverIcon.gif");
ImageIcon pressedIcon = new ImageIcon("images/pressedIcon.gif");

// 생성자에서 normalIcon 달기
// 디폴트 아이콘
JButton btn = new JButton("test",normalIcon); 
// 나머지 아이콘 달기
btn.setRolloverIcon(rolloverIcon); // 마우스가 올라갔을 때
btn.setPressedIcon(pressedIcon);   // 눌렸을 때

// normalIcon 수정
btn.setIcon(new ImageIcon("images/newIcon.git"));


버튼과 레이블의 정렬

버튼과 레이블 컴포넌트는 정렬 기능을 이용하면, 컴포넌트 내의 문자열과 이미지의 위치를 조정할 수 있다. 정렬은 수평, 수직 정렬로 구분된다.

  • 수평 정렬 : JButton, JLabel의 void setHorizontalAlignment(int align) 사용
    • align -> SwingConstants.LEFT, SwingConstants.CENTER, SwingConstants.RIGHT
  • 수직 정렬 : JButton, JLabel의 void setVerticalAlignment(int align) 사용
    • align -> SwingConstants.TOP, SwingConstants.CENTER, SwingConstants.BOTTOM


4. JCheckBox


JCheckBox를 이용하면 선택과 해제의 두 상태만 가지는 체크박스를 만들 수 있다. 체크박스는 문자열과 체크박스 이미지로 구성된다. 생성자는 다음과 같다.

JCheckBox() // 빈 체크박스
JCheckBox(String text) // 문자열 체크박스
JCheckBox(String text, boolean selected) // 문자열 체크박스
JCheckBox(Icon image) // 이미지 체크박스
JCheckBox(Icon image, boolean selected) // 이미지 체크박스
JCheckBox(String text, Icon image) // 문자열과 이미지를 가진 체크박스
JCheckBox(String text, Icon image, boolean selected) // 문자열과 이미즈를 가진 체크박스

selected가 true면 선택 상태로 초기화, 디폴트는 해제 상태이다.

이미지 체크박스

이미지 체크박스는 일반적으로 선택하면 체크가 표시되는게 아니라 선택시 별도의 이미지를 나타내게 할 수 있다. 선택 상태의 이미지는 JCheckBox의 setSelectedIcon(ImageIcon) 메서드를 사용한다.

ImageIcon cherryIcon = new ImageIcon("경로");
ImageIcon selectedCherryIcon = new ImageIcon("경로");
// 체크 해제 상태 이미지만 가진 체크 박스
JCheckBox cherry = new JCheckBox("체리",cherryIcon);
// 선택 상태 이미지 등록
cherry.setSelectedIcon(selectedCherryIcon);
cherry.setBorderPainted(true); // 체크박스 외곽선 보이도록 설정


JCheckBox에서 Item 이벤트 처리

Item 이벤트는 체크박스, 라디오버튼의 선택 상태가 바뀔 때 발생하는 이벤트이다. 이미 선택 상태인 라디오버튼을 누르는 경우 선택 상태에 대한 변화가 없기 때문에 Item 이벤트는 발생하지 않는다. 참고로 체크박스는 여러 개의 선택이 가능하고, 라디오버튼은 하나만 선택할 수 있는 것이다. 선택 행위는 마우스를 통해 하지만 자바 코드로도 가능하다. 마우스든 코드이든 선택 상태가 변하면 Item 이벤트가 발생한다.

JCheckBox c = new JCheckBox("선택");
c.setSelected(true); // 선택 상태로 설정, false면 해제 상태로 설정


ItemListener 인터페이스

Item 이벤트 리스너는 ItemListener 인터페이스를 상속받아 만들어지고 하나의 메서드로 구성된다.

void itemStateChanged(ItemEvent e) // 체크박스 선택/해제 상태가 변하는 경우 호출

주의할 점이 메서드가 호출된 시점에는 이미 체크박스는 화면에서 상태가 바뀌어 있다는 점이다.

ItemEvent 객체

Item 이벤트가 발생하면 ItemEvent 객체가 생성되어 itemStateChanged 인자로 전달된다. ItemEvent가 제공하는 메서드는 다음과 같다.

  • int getStateChange() : 리턴 값은 선택된 경우 ItemEvent.SELECTED, 해제된 경우, ItemEvent.DESELECTED
  • Object getItem() : 이벤트를 발생시킨 아이템 객체 리턴, 체크박스의 경우 JCheckBox 컴포넌트 레퍼런스 리턴

세 과일에 대해 체크박스를 만들고, 사용자가 과일을 선택하거나 해제하면 바로 선택된 과일의 합산 가격을 보여주는 응용프로그램 작성

public class CheckBoxItemEventEx extends JFrame {
	private JCheckBox [] fruits = new JCheckBox [3]; // 체크박스 배열
	private String [] names = {"딸기", "바나나", "배"}; //체크박스 문자열로 사용할 것
	private JLabel sumLabel; // 계산합 
	
	public CheckBoxItemEventEx() {
		setTitle("아이템 이벤트 예시");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container c = getContentPane();
		c.setLayout(new FlowLayout());
		
		c.add(new JLabel("딸기 100원, 바나나 500원, 배 2000원"));
		
		
		MyItemListener listener = new MyItemListener();
		for(int i=0; i<fruits.length; i++) {
			fruits[i] = new JCheckBox(names[i]); // 문자열 체크박스 만들기
			fruits[i].setBorderPainted(true); // 외곽선 설정
			fruits[i].addItemListener(listener); // 체크박스에 리스너 등록
            c.add(fruits[i]); // 체크박스 컨텐트팬에 붙이기			
		}
		
		sumLabel = new JLabel("현재 0원 입니다."); // 합산 가격 레이블 생성
		c.add(sumLabel); // 컨텐트팬에 레이블 붙이기
		
		setSize(250,200);
		setVisible(true);
	}
	
	
	class MyItemListener implements ItemListener {
		private int sum = 0; 

		
		public void itemStateChanged(ItemEvent e) {
            // 선택되었다면 합산
			if(e.getStateChange() == ItemEvent.SELECTED) { 
				if(e.getItem() == fruits[0]) 
					sum += 100;
				else if(e.getItem() == fruits[1]) 
					sum += 500;
				else 
					sum += 20000;
			}
			else { // 선택 해제 되었다면 빼주기
				if(e.getItem() == fruits[0]) 
					sum -= 100;
				else if(e.getItem() == fruits[1]) 
					sum -= 500;
				else 
					sum -= 20000;
			}
			sumLabel.setText("현재 "+ sum + "원 입니다."); // 레이블 수정
		}
	}
	public static void main(String [] args) {
		new CheckBoxItemEventEx();
	}
} 


5. JRadioButton


JRadioButton는 생성, 메서드, 이벤트 처리에 있어서 체크박스와 동일하지만, 라디오버튼은 여러 개가 하나의 버튼 그룹을 형성하고 그룹 내에서 하나만 선택이 가능하다. 생성자는 다음과 같다.

JRadioButton() // 빈 라디오버튼
JRadioButton(String text) // 문자열 라디오버튼
JRadioButton(String text, boolean selected) // 문자열 라디오버튼
JRadioButton(Icon image) // 이미지 라디오버튼
JRadioButton(Icon image, boolean selected) // 이미지 라디오버튼
JRadioButton(String text, Icon image) // 문자열과 이미지를 가진 라디오버튼
JRadioButton(String text, Icon image, boolean selected) // 문자열과 이미즈를 가진 라디오버튼


그룹 생성

라디오버튼은 여러 개가 하나의 버튼 그룹을 형성한다고 했다. 따라서 ButtonGroup 클래스를 이용해서 버튼들을 묶어줘야 한다.

ButtonGroup g = new ButtonGroup();
JRadioButton apple = new JRadioButton("사과");
JRadioButton pear = new JRadioButton("배");

// 그룹에 넣어주기만 하면 그룹 처리 완료
group.add(apple);
group.add(pear);

// 버튼별로 원래 하던 식으로 컨테이너에 넣기
container.add(apple);
container.add(pear);

// isSelected 예시, fruits[0]은 라디오버튼
if(fruits[0].isSelected()) 
					sum -= 100;

체크박스는 개별적으로 작동하므로 하나의 체크박스를 선택하면 그 체크박스에만 item 이벤트가 발생한다. 하지만 라디오버튼의 경우는 하나만 선택이 가능하다. 따라서 선택 상태가 바뀌게 되면 2개의 이벤트가 발생한다. 하나는 기존 상태에서의 해제, 하나는 새로운 선택에 대한 이벤트가 발생한다. 그러나 선택상태의 버튼을 누른다면 변화가 없으므로 이벤트도 발생하지 않는다.
체크박스에서는 ItemEvent의 getItem 메서드를 사용해서 체크박스의 레퍼런스를 가져와서 사용했다. 라디오박스에서도 이를 사용해도 되지만 라디오버튼은 하나만 체크하므로 라디오버튼.isSelected() 로 라디오버튼이 선택되었는지 안되었는지 확인하는 것이 편할 수도 있다.


참고
13장 스레드 부분을 공부하다가 발견한 것이 있다. 지금까지는 모든 것을 컨텐트팬에 붙이고 화면에 출력했어서 사용할 일이 없었는데 스레드에서 실행되다가 중간에 컨텐트팬에 레이블같은 것을 붙인다면 붙이고 나서 추가된 레이블이 보이도록 컨텐트 팬을 다시 그려줘야 한다. contentPane.repaint()를 해주면 된다.



본 포스팅은 ‘명품 JAVA Programming’를 읽고 공부한 내용을 바탕으로 작성하였습니다.


© 2021. By Backtony