[JAVA] Day 02 AWT 이벤트 리스너
by 효기’s
AWT
GUI 프로그래밍이란 DOS(CUI방식)와 같은 방식의 텍스트 기반 운영체제가 아닌 그래픽을 이용하여 사용자와 프로그램 간의 상호작용을 할 수 있도록 해주는 인터페이스를 의미한다. 자바에서는 이러한 그래픽 프로그래밍을 지원하기 위해 나온것이 AWT인 것이다.
AWT는 GUI 프로그래밍을 제작하기 위해 자바에서 제공하는 라이브러리를 모아놓은 것이다.
AWT는 모든 GUI 프로그램에 사용되는 컴포넌트 및 툴킷을 제공하고 있으며 향후 JFC와 같은 스윙(Swing) 및 java2D의 모태가 되는 개념이다.
AWT는 운영체제에 구해받지 않고 쓸 수 있도록 운영체제의 것을 그대로 사용하지 않고 공통적이고 기본적인 컴포넌트를 추상화시켜 제공한다.
단점을 극복하기 위해 개발된 것이 JFC (Java Foundation Classes)이다.
Container
자신의 영역에 컴포넌트를 포함시키고 관리하는 역할을 하며 컨테이너가 다른 컨테이너를 포함 할 수도 있다.
컴포넌트도 또한 컨테이너에 부착시키지 않으면 독자적으로 화면에 출력될 수가 없고 반드시 컨테이너에 부착을 시켜야만 화면에 출력이 될 수 있다.
컨테이너에 컨포넌트를 부착시키기 위해 add() 메서드를 사용한다.
컨테이너는 창을 말하는 것이고 컴포넌트는 소프트웨어의 모듈을 말한다.(버튼..)
Container → Frame (하위)
Window 클래스의 하위 클래스로 일반적인 응용프로그램에서 윈도우를 생성하기 위해 사용되는 클래스이다.
Frame 클래스의 상위 클래스인 window 클래스는 타이틀 메뉴 등이 지원되지 않기 때문에
일반적으로 사용되지 않고 Frame 클래스를 사용한다.
Frame 클래스는 기본적으로 경계선(Border), 타이틀, 메뉴, 시스템상자(최소화, 최대화, 종료 버튼) 등의 기능을 제공한다.
Frame은 다른 윈도우에 속해 있지 않은 윈도우로 최상위 레벨 윈도우라 한다.
setSize() setBounds() 메서드 등을 이용하여 windows의 크기를 설정한 후 setVisible(), show() 메서드를 통해서 화면에 출력 시킬 수 있다.
Frame 코드 (300 x 300) 크기의 창만 나옴
package 고급반;
import java.awt.Frame;
public class Day02 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Frame f = new Frame();
f.setSize(300, 300);
f.setVisible(true);
}
}
package 고급반Day02;
import java.awt.Frame;
public class FrameEx2 extends Frame {
public FrameEx2() {
super("Titlebar2");
setSize(300, 300);
setVisible(true);
}
public static void main(String[] args) {
FrameEx2 fe = new FrameEx2();
}
}
Container → Panel (하위)
컴포넌트들을 그룹 별로 묶어서 처리할때 주로 사용
Frame에 컴포넌트를 직접 붙이지 않고 Panel에 그룹별로 붙이고, 다시 Panel을 Frame에 붙이는 경우가 많다.
다른 Panel을 생성하여 자신에게 붙일 수도 있어 윈도우 프로그램을 만들때는 여러개의 Panel을 사용하는 경우가 많다.
Container - Dialog (하위)
메인 윈도우 외에 메시지를 출력하거나, 사용자로부터 데이터를 입력 받을 때 주로 사용하는 컨테이너이다.
Dialog 클래스로부터 상속을 받아 새로운 기능을 가진 대화상자를 만드는데 사용된다.
Component
모든 컴포넌트들의 super 클래스로서 GUI 프로그램을 구성하는 구성단위로
각 컴포넌트들에서 공통으로 사용되어지는 메서드들을 가지고 있다.
Component - 기본
Component - Button
package 고급반Day02;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
public class ButtonEx extends Frame {
public static void main(String[] args) {
Frame f = new Frame("Frame");
Panel p = new Panel();
Button b1 = new Button("");
Button b2 = new Button("Button2");
Button b3 = new Button("Button3");
Button b4 = new Button("Button4");
b1.setLabel("Button1");
p.add(b1);
p.add(b2);
p.add(b3);
p.add(b4);
f.add(p);
f.setLocation(300, 300);
f.setSize(300, 100);
f.setVisible(true);
}
}
Component - Checkbox
그룹으로 묶을 때는 CheckboxGroup 클래스를 사용한다.
package 고급반Day02;
import java.awt.Checkbox;
import java.awt.Frame;
import java.awt.Panel;
public class CheckBoxEx00 {
public static void main(String[] args) {
Frame f = new Frame("...");
Panel p = new Panel();
Checkbox ck1 = new Checkbox("1", true);
Checkbox ck2 = new Checkbox("2");
Checkbox ck3 = new Checkbox("3");
p.add(ck1);
p.add(ck2);
p.add(ck3);
f.add(p);
f.setSize(300, 100);
f.setVisible(true);
}
}
package 고급반Day02;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Frame;
import java.awt.Panel;
public class RadioCheckboxEx {
public static void main(String[] args) {
Frame f = new Frame("...");
Panel p = new Panel();
CheckboxGroup group = new CheckboxGroup();
Checkbox radio1 = new Checkbox("1", group, false);
Checkbox radio2 = new Checkbox("2", group, false);
Checkbox radio3 = new Checkbox("3", group, true);
p.add(radio1);
p.add(radio2);
p.add(radio3);
f.add(p);
f.setSize(300, 100);
f.setVisible(true);
}
}
Component - 텍스트
텍스트를 다루는 클래스의 super 클래스로 텍스트를 처리하는 각종 메서드를 가지고 있다.
독립적으로는 생성되지 못한다.
Component - TextField
한줄 내의 텍스트를 입력받거나 편집할 수 있는 컴포넌트이다.
한 줄에 표시할 수 있는 칼럼수를 지정할 수 있고 반향 문자(Echo Character)를 지정하면 입력되는 문자 대신 반향 문자로 지정한 문자로 출력된다.
package 고급반Day02;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextField;
public class TextFieldEx extends Frame {
public static void main(String[] args) {
Frame f = new Frame("EXam");
Panel p = new Panel();
TextField tf1 = new TextField("Id input: ", 12);
TextField tf2 = new TextField("password", 10);
tf1.selectAll();
tf2.selectAll();
tf2.setEchoChar('*'); // 비밀번호를 숨김
p.add(tf1);
p.add(tf2);
f.add(p);
f.setSize(300, 100);
f.setVisible(true);
}
}
Component - TextArea
여러 줄의 텍스트를 사용자로부터 입력 받거나 편집할 수 있는 컴포넌트이다.
화면에 출력되는 영역이 벗어나면 스크롤바 표시 방식에 따라 자동으로 스크롤바가 생성된다.
사용자가 필요에 따라 일부 스크롤바만 나타나게 할 수도 있다.
LayoutManager
컨테이너는 자기 자신에 컴포넌트를 붙일 때 어디에, 어떤 방식으로 배치하여 붙일 것인가를 이미 결정하고 있다.
미리 정해진 레이아웃에 따라 컴포넌트들을 자동으로 배치하는 기능을 가지고 있는 객체를 컨테이너들은 가지고 있는데 이것을 배치관리자(LayoutMananger)라 한다.
배치관리자는 각자 다른 방식으로 배치기능을 가지고 있으며 컨테이너는 기본적으로 하나의 배치관리자를 가지고 있다.
사용자가 임의로 배치관리자를 다시 설정할 수 있으며 배치 관리자를 제거하고 수동으로 좌표를 이용해서 배치 할 수도있다.
LayoutManager - FlowLayout
컴포넌트들을 수평으로 순서대로 늘어놓는 배치 기능을 가지고 있다.
처음에 배치를 하게되면 상단 중앙부터 배치가 되는데 배치를 하다가 더 이상 배치할 공간이 없으면 자동으로 다음줄로 이동하여 배치하게 된다.
컴포넌트를 배치할 때 컴포넌트의 간격을 갭이라고 하는데 컴포넌트들 사이의 수평, 수직간 간격을 설정할 수 있다.
LayoutManager - BorderLayout
컨테이너 영역을 5개의 영역으로 분할하여 컴포넌트를 배치하는 관리자이다.
기본적으로 컴포넌트를 BorderLayout에 붙일 때 아무런 영역을 지정하지 않은 경우는 기본적으로 CENTER영역에 붙이게 된다.
Center : 다른 영역에 아무것도 존재하지 않으면 그 영역까지 포함해서 영역이 잡히게 된다.
SOUTH, NORTH : 컴포넌트의 높이는 제대로 나타나지만 폭의 길이는 인정되지 않는다.
WEST, EAST : 컴포넌트의 폭의 길이는 제대로 나타나지만 높이는 제대로 인정되지 않고 항상 그 영역의 길이 만큼 잡히게 된다.
package 고급반Day02;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
public class BorderLayoutEx {
public static void main(String[] args) {
Frame f = new Frame("BorderLayout");
Button east = new Button("EAST");
Button west = new Button("WEST");
Button center = new Button("CENTER");
Button south = new Button("SOUTH");
Button north = new Button("NORTH");
f.add(east, BorderLayout.EAST);
f.add(west, BorderLayout.WEST);
f.add(center, BorderLayout.CENTER);
f.add("South", south);
f.add("North", north);
f.setLocation(300, 300); // 초기위치
f.setSize(500, 500); // 크기
f.setVisible(true);
}
}
LayoutManager - CardLayout
여러 개의 카드를 쌓아둔 것처럼 컴포넌트를 하나만 보여주는 배치관리자이다.
맨 위의 컴포넌트만 보여주므로 한번에 하나의 컴포넌트만 볼 수 있다.
CardLayout에는 맨 뒤에 위치할 컴포넌트를 지정할 수 있는 메서드가 지원되며, 또한 그 다음에 나올 컴포넌트를 이동 시킬수있는 메서드를 지원한다.
package 고급반Day02;
import java.awt.Button;
import java.awt.CardLayout;
import java.awt.Frame;
import java.awt.Panel;
public class CardLayoutEx extends Frame {
CardLayout card;
Panel first_panel, second_panel, third_panel;
public CardLayoutEx() {
super("CardLayout");
card = new CardLayout();
setLayout(card);
first_panel = new Panel();
first_panel.add(new Button("1"));
first_panel.add(new Button("2"));
second_panel = new Panel();
second_panel.add(new Button("3"));
second_panel.add(new Button("4"));
third_panel = new Panel();
third_panel.add(new Button("5"));
third_panel.add(new Button("6"));
add("1", first_panel);
add("2", second_panel);
add("3", third_panel);
}
public void rotate() {
for (int i = 0; i < 2; i++) {
try {
Thread.sleep(3000);
} catch (Exception e) {
e.printStackTrace();
}
card.next(this);
}
}
public static void main(String[] args) {
CardLayoutEx clt = new CardLayoutEx();
clt.setBounds(200, 200, 200, 100);
clt.setVisible(true);
clt.rotate();
}
}
이벤트의 정의
윈도우 프로그래밍에서 어떤 특정한 행동이 발생한 그 자체를 의미한다.
이벤트 소스는 이벤트가 발생할 수 있는 대상을 의미하고 그 대상으로 부터 이벤트가 발생하면 발생된 이벤트를 처리해서 결과를 낼 수 있도록 해주는 것을 이벤트 핸들러 라한다.
자바에서의 이벤트 처리
프로그램이 실행중에 운영체제 os가 해당 프로그램에서 이벤트가 발생이 되는지를 검사한다.
이때 이벤트가 발생되면 운영체제가 JVM에게 이벤트를 전달하고 JVM은 발생된 이벤트를 처리하기 위하여 이벤트 객체를 생성한다.
그런 후 이벤트 처리하기 위하여 이벤트 객체를 가지고 핸들러를 호출한다.
이벤트 소스
이벤트 소스는 이벤트가 발생되는 컴포넌트를 말한다. 즉, 버튼, 체크박스, 리스트, 프레임, 마우스 같은 컴포넌트들이 이벤트 소스이다.
이벤트 리스너
이벤트 소스에서 이벤트가 발생하는지를 검사하고 있다가 이벤트가 발생이 되면 실제적으로 이벤트를 처리할 수 있도록 만든 인터페이스 이다.
이벤트 핸들러
이벤트 리스너에 전달된 이벤트를 실제로 처리할 수 있도록 이벤트 리스너에 포함되어 있는 메서드로 발생된 이벤트 객체를 받아와서 실제적으로 처리해 주는 기능을 가지고 있다.
이벤트 어댑터 클래스
어댑터 클래스는 이벤트 리스너 인터페이스들 중에서 추상 매서드가 2개 이상 존재하는 인터페이스를 구현한 추상 클래스이다.
인터페이스에 있는 모든 메서드를 빈 메서드로 재 정의하였기 때문에 인터페이스를 구현하여 불필요한 메서드를 재정의하는 수고를 덜어준다.
Adapter클래스를 상속받은 클래스에서는 자신이 필요한 메서드만을 재정의 하면 된다.
이벤트와 리스너 종류 - ActionEvent
ActionEvent는 버튼이 눌렸다던가, 리스트, 메뉴 등의 컴포넌트가 선택이 되었을 때 발생하는 이벤트이다.
텍스트 필드에서 엔터를 쳤을 때도 발생되는 이벤트이다.
ActionEvent - ItemEvent
체크박스, 리스트, 초이스 컴포넌트에서 항목을 선택되거나 선택이 해제 되었을때 발생하는 이벤트이다.
ActionEvent - TextEvent
텍스트 컴포넌트(TextField, TextArea)에서 키가 입력이 되어 내용이 바뀌었을 때 발생하는 이벤트이다.
내용이 바뀔때마다 발생하므로 주의해서 사용해야 된다.
사용자가 입력할 때마다 처리해야 되는 경우가 있을 경우에 사용하는 이벤트이다.
ActionEvent - KeyEvent
사용자가 키보드와 같은 입력장치를 통해서 키 입력을 했을 때 발생하는 이벤트이다.
Adapter클래스 활용
Adapter 클래스를 사용할 때는 예제에서 봤던 것 처럼 Adapter클래스로 부터 상속받는 클래스를 생성하여 처리를 하였다.
Anonymous 클래스를 이용하는 방법과 inner 클래스를 이용하는 방법이 있다.
WindowEvent
윈도우와 관련되어 윈도우가 활성화, 아이콘화, 비활성화 및 창이 닫힐 때 발생하는 이벤트이다.
ActionListener
ActionEvent를 처리하는 이벤트 리스너가 ActionListener 이다.
ItemListener
ItemEvent를 처리하는 이벤트 리스너가 ItemListener 이다.
TextListener
TextEvent를 처리하는 이벤트 리스너가 TextListener이다.
KeyListener
KeyEvent를 처리하는 이벤트 리스너가 KeyListener이다.
MouseListener
마우스와 관련 있는 이벤트 중 MouseEvent를 처리하는 이벤트 리스너가 MouseListener이다.
MouseMotionListener
마우스가 관련 있는 이벤트 중 MouseMotionEvent를 처리하는 이벤트 리스너가 MouseMotionListener이다.
WindowListener
WindowEvent를 처리하는 이벤트 리스너가 WindowListener 이다.
Adapter 클래스 활용
Adapter 클래스를 사용할 때는 예제에서 봤던 것 처럼 Adapter 클래스로부터 상속 받는 클래스를 생성하여 처리를 하였다.
이 방법보다 좀 더 효율적으로 처리 할 수 있도록 Anonymous 클래스를 이용하는 방법과 inner 클래스를 이용하는 방법이 있다.
- Action이벤트 예제
package 고급반Day02;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
public class ActionEventEx extends Frame implements ActionListener, WindowListener {
Panel p; // 패널
Button input, exit;
TextArea ta; // 텍스트 영역을 나타내는 변수
public ActionEventEx() {
super("ActionEvent Test");
p = new Panel();
input = new Button("input");
exit = new Button("exit");
ta = new TextArea();
// 이벤트 소스를 이벤트 핸들러에 연결
input.addActionListener(this);
exit.addActionListener(this);
super.addWindowListener(this); // 윈도우 닫기버튼
p.add(input);
p.add(exit);
add(p, BorderLayout.NORTH);
add(ta, BorderLayout.CENTER);
setBounds(300, 300, 300, 200);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent ae) { // 이벤트 핸들러
String name;
name = ae.getActionCommand();
if (name.equals("input"))
ta.append("input...\n");
else {
ta.append("잠시 대기 중...\n");
try {
Thread.sleep(2000);
} catch (Exception e) {
}
System.exit(0);
}
}
public static void main(String[] args) {
new ActionEventEx();
}
@Override
public void windowOpened(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
System.exit(0);
}
@Override
public void windowClosed(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowIconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeiconified(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDeactivated(WindowEvent e) {
// TODO Auto-generated method stub
}
}
package 고급반Day02;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class AdapterEx extends Frame implements ActionListener {
Panel p1, p2, p3;
TextField tf;
TextArea ta;
Button b1, b2;
public AdapterEx() {
super("Adapter");
p1 = new Panel();
p2 = new Panel();
p3 = new Panel();
tf = new TextField(35); // 가로넓이
ta = new TextArea(10, 35); // 10개의 행과 각 행마다 최대 35개의 문자를 나타내는 열을 가짐
b1 = new Button("Clear");
b2 = new Button("Exit");
p1.add(tf); // 텍스트 필드
p2.add(ta); // 텍스트 Area
p3.add(b1); // clear 버튼
p3.add(b2); // exit 버튼
add("North", p1); // 맨위
add("Center", p2); // 가운데
add("South", p3); // 맨아래
// 컴포넌트의 위치
setBounds(300, 200, 300, 300); // x좌표 300, y좌표 200, 너비 300, 높이 300
setVisible(true);
// 엑션 이벤트를 처리하기위한 클래스 this의 액션 리스너를 등록
b1.addActionListener(this);
b2.addActionListener(this);
// 텍스트 필드에 키 입력 이벤트를 처리
tf.addKeyListener(new KeyEventHandler(tf, ta));
// 현재 창의 상태 변경 이벤트를 처리
addWindowListener(new WindowEventHandler());
}
@Override
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
if (str.equals("Clear")) {
ta.setText("");
tf.setText("");
tf.requestFocus(); // 키보드로 해당 텍스트 필드에 텍스트를 입력
} else if (str.equals("Exit")) {
System.exit(0);
}
}
public static void main(String[] args) {
new AdapterEx();
}
}
class KeyEventHandler extends KeyAdapter {
TextField tf;
TextArea ta;
public KeyEventHandler(TextField tf, TextArea ta) {
this.tf = tf;
this.ta = ta;
}
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
ta.append(tf.getText() + "\n");
tf.setText("");
}
}
}
class WindowEventHandler extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
Anoymous Class (익명 클래스)
이름이 없는 클래스이며 클래스의 정의와 인스턴스 생성을 동시에 수행한다.
코드 내에서 한번 사용하고 버릴 클래스를 간단하게 구현할때 유용하다.
주로 한 번만 사용할 리스너나 콜백 등을 구현할 때 많이 사용한다.
Member Inner Class (멤버 이너 클래스)
다른 클래스 내부에 정의된 클래스로, 외부 클래스의 인스턴스와 연결되어 있다.
주로 외부 클래스와 밀접한 관련이 있는 보조 클래스를 정의 할때 사용한다.
package 고급반Day02;
import java.awt.Button;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
class FAdapterEx extends Frame implements ActionListener {
Panel p1, p2, p3;
TextField tf;
TextArea ta;
Button b1, b2;
public FAdapterEx() {
super("Adapter");
p1 = new Panel();
p2 = new Panel();
p3 = new Panel();
tf = new TextField(35);
ta = new TextArea(10, 35);
b1 = new Button("Clear");
b2 = new Button("Exit");
p1.add(tf);
p2.add(ta);
p3.add(b1);
p3.add(b2);
add("North", p1);
add("Center", p2);
add("South", p3);
setBounds(300, 200, 300, 300);
setVisible(true);
b1.addActionListener(this);
b2.addActionListener(this);
tf.addKeyListener(new KeyEventHandler());
// anoymous class
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// TODO Auto-generated method stub
System.exit(0);
}
});
}
@Override
public void actionPerformed(ActionEvent e) {
String str = e.getActionCommand();
if (str.equals("Clear")) {
ta.setText("");
tf.setText("");
tf.requestFocus();
} else if (str.equals("Exit")) {
System.exit(0);
}
}
// 멤버 이너클래스
class KeyEventHandler extends KeyAdapter {
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == KeyEvent.VK_ENTER) {
ta.append(tf.getText() + "\n");
tf.setText("");
}
}
}
}
public class AdapterEx2 {
public static void main(String[] args) {
new FAdapterEx();
}
}
'Studying' 카테고리의 다른 글
웹 프로그래밍 Web programming 이란? (0) | 2023.09.19 |
---|---|
아두이노와 MCU 그리고 LED 저항 읽는법 알아보기 (0) | 2023.04.04 |
영상 흐림과 선명화와 경계선 검출 다중 영상처리 개념 (0) | 2023.03.24 |
픽셀 기반 영상처리와 영역 기반 영상처리가 무엇인가? (0) | 2023.03.17 |
픽셀(pixel)과 히스토그램 평활화가 무엇인가? (2) | 2023.03.13 |
블로그의 정보
감성 개발자 효기
효기’s