자바 수업 5일차
* 메소드를 오버라이딩하는 경우 상위 클래스의 메소드 한정자보다 허용 범위가 넓은 경우에만 허용되고, 그 반대 경우는 허용되지 않는다.
- 상위 클래스에서 public으로 사용된 메소드를 하위 클래스에서 한정자 없이 사용하거나 protected로 메소드를 오버라이딩 할 수 없다.
- 한정자의 허용 범위는 "public" -> "protected" -> "한정자 사용 안 함" 순서
- private는 상속되지 않기 때문에 오버라이딩의 대상이 되지 않는다.
a. 한정자의 허용 범위가 넓어지는 경우는 허용된다.
| class AAA { void aa(int a, int b) { // 한정자 없이 메소드 선언 System.out.println(a+b); } } class BBB extends AAA { public void aa(int a, int b) { // public 한정자 사용. 허용됨. System.out.println(a*b); } } | cs |
b. 한정자의 허용 범위가 좁아지는 경우는 허용되지 않는다. 컴파일 오류.
| class AAA { public void aa(int a, int b) { // public 메소드 선언 System.out.println(a+b); } } class BBB extends AAA { protected void aa(int a, int b) { // protected 한정자 사용. 허용 안 됨. System.out.println(a*b); } } | cs |
* 메소드를 오버라이딩하여 사용할 때 유용하게 쓸 수 있는 주석
- @Override 주석 : 자바 컴파일러는 @Override 주석이 사용되어 메소드가 선언되면 상위 클래스의 메소드와 정확하게 일치하는지 검사하여 일치하지 않는 경우에는 컴파일 오류를 발생시킨다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class OIa { public void show(String str) { System.out.println("상위 클래스의 메소드 show(String str) 수행 " +str); } } class OIb extends OIa { @Override public void shaw(String str) { // @Override 주석을 사용하여 메소드를 선언. // 상위 클래스의 오버라이딩 메소드와 일치하지 않아 // 오류를 발생시킨다. System.out.println("하위 클래스의 메소드 show(String str) 수행 " +str); } } public class OverridingTest3 { public static void main(String args[]) { OIb oib = new OIb(); oib.show("처음 시작하는 자바"); } } | cs |
* 예약어 super
1. 하위 클래스에 의해 가려진 상위 클래스의 멤버 변수나 메소드에 접근할 때 사용한다.
super.멤버 변수
super.메소드 이름(매개 변수)
2. 상위 클래스의 명시적 생성자를 호출하기 위해 사용한다.
super(매개 변수)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | class SD1 { public int i1; public double d1; public SD1(int i1) { System.out.println("SD1(int i1) 생성자 수행"); this.i1 = i1 * i1; // this.i1은 객체 변수를 의미 System.out.println(i1 + "의 2제곱은 : " +this.i1); } public SD1(double d1) { System.out.println("SD1(double d1) 생성자 수행"); this.d1 = d1 * d1; System.out.println(d1 + "의 2제곱은 : " +this.d1); } } class Sub1 extends SD1 { public Sub1(int i1) { super(i1); // 상위 클래스의 생성자 호출 System.out.println("Sub1(int i1) 생성자 수행"); this.i1 = this.i1 * i1; // this.i1은 상속받은 객체 변수를 의미 System.out.println(i1 + "의 3제곱은 : " +this.i1); } public Sub1(double d1) { super(d1); // 상위 클래스의 생성자 호출 System.out.println("Sub1(int d1) 생성자 수행"); this.d1 = this.d1 * d1; System.out.println(d1 + "의 3제곱은 : " +this.d1); } } public class SuperTest3 { public static void main(String[] args) { Sub1 sub1 = new Sub1(10); // 생성자에 의해 결과가 출력된다. Sub1 sub2 = new Sub1(10.5); } } | cs |
* Object 클래스
- java.lang 패키지에 속해 있는 라이브러리 클래스이다.
- 모든 자바 클래스의 최상위 클래스이다.
- 명시적으로 상위 클래스가 지정된 경우에도, 그 상위 클래스의 상위 클래스가(계속 반복 가능) 최종적으로는 Object 클래스이다.
- 즉, Object 클래스에서 선언된 모든 속성과 기능은 모든 자바 클래스에 상속되기 때문에 자유롭게 사용할 수 있다.
* Object 클래스에 선언된 toString() 메소드
- 객체의 클래스명과 메모리에서의 주소를 16진수로 반환하는 메소드이다.
| public String toString() { return getClass().getName() + // 현재 클래스의 이름을 반환한다. "@" + Integer.toHexString(hashCode()); // hashCode()의 값은 객체가 저장된 메모리의 10진 주소이다. // 이 값을 10진수로 변환하여 반환한다. // Integer 클래스의 toHexString()은 클래스 메소드로서 // 10진수를 16진수로 변환하는 메소드이다. } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class AAA { public int a; } public class ObjectMethodTest1 { public static void main(String args[]) { AAA aa = new AAA(); System.out.println(aa); // 객체 aa의 toString() 메소드가 자동으로 호출된다. // (Object 클래스로부터 상속되었음) System.out.println(aa.toString()); // 객체 aa의 toString() 메소드를 명시적으로 호출한다. // 결과가 같다. Integer ii = new Integer(99); // Integer 클래스로부터 객체 ii를 생성한다. // 객체의 값은 99. System.out.println(ii); // 객체 ii의 toString() 메소드가 자동으로 호출된다. System.out.println(ii.toString()); // 명시적으로 toString() 메소드를 호출한다. // 결과가 같다. } } | cs |
* 동등 연산자(==)
- 참조 자료형의 변수에 적용할 수는 있지만, 예상치 않은 결과를 나타낸다.
- 참조 자료형 변수는 값이 실제 값이 아니라 객체가 저장된 주소이기 때문이다.
* Object 클래스에 선언된 equals() 메소드
| public boolean equals(Object obj) { return (this == obj); // 두 객체 변수의 값(주소)이 같으면 true, 아니면 false 반환 } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | class Box11 { public int width; public int height; public int depth; public Box11(int w, int h, int d) { width = w; height = h; depth = d; } } public class ObjectMethodTest4 { public static void main(String[] args) { Box11 b1 = new Box11(10,20,30); Box11 b2 = new Box11(10,20,30); Box11 b3 = b2; System.out.println(b1.equals(b2) ? "b1과 b2는 같다" : "b1과 b2는 같지 않다"); // equals() 메소드를 이용하여 객체를 비교 System.out.println(b2.equals(b3) ? "b2와 b3는 같다" : "b2와 b3는 같지 않다"); // (동등 연산자와 같은 결과) String s1 = new String("처음 시작하는 자바"); String s2 = new String("처음 시작하는 자바"); System.out.println(s1.equals(s2) ? "s1과 s2는 같다" : "s1과 s2는 같지 않다"); // String 클래스의 객체를 이용하여 비교 // (String 클래스에 오버라이딩된 equals() 수행) } } | cs |
* final : 모두 변하는 것을 방지하기 위해 사용한다.
1. 메소드 지역 변수나 객체 변수에 final을 붙여 상수로 사용한다.
| class AAA { public final int MAX = 100; // 객체 변수에 final을 사용하여 상수로 지정. ...... public void temp() { final int max = 50; // 메소드 지역 변수를 final로 지정. ...... max++; // 오류 발생. final로 지정된 지역 변수의 값을 변경할 수 없음. } } class BBB { ...... AAA aa = new AAA(); aa.MAX = 200; // 오류 발생. final로 지정된 객체 변수의 값을 변경할 수 없음. ...... } | cs |
2. 메소드에 final을 붙여 선언하는 경우, 하위 클래스에서 이 메소드를 오버라이딩 할 수 없다는 의미이다.
| class AAA { final void calculate() { // 메소드를 final로 선언. System.out.println("이 메소드는 final 메소드"); } } class BBB extends AAA { void calculate() { // 오류 발생. final로 선언된 메소드 오버라이딩 금지. System.out.println("final 메소드를 중첩하는 메소드"); } } | cs |
3. 클래스 선언에도 사용할 수 있다. final이 붙은 클래스는 상속을 허용하지 않는다.
| final class AAA { // 클래스를 final로 선언. ...... } class BBB extends AAA { // 오류 발생. final로 선언된 클래스 상속 금지. ...... } | cs |
☞ 다형성, 추상 클래스, 인터페이스
* 상속된 관계에서 객체의 형 변환
- 상위 클래스 형의 객체 변수에 하위 클래스에서 생성된 객체의 배정을 허용한다.
- 반대로 하위 클래싀 형의 객체 변수에 상위 클래스에서 생성된 객체의 배정은 허용하지 않는다.
| Object o1 = new Scanner(); // 가능. 단, 이 객체 변수를 통해서는 Object o2 = new Box(); // Object 클래스의 속성과 기능만 사용 가능. Scanner s = new Object(); // 오류 발생. Random r = new Object(); // 상위 클래스의 객체를 배정할 수 없음. | cs |
* instanceof 연산자
- 객체가 특정 클래스로부터 생성된 객체인지를 판별하여 true 또는 false를 반환한다.
- [형식]
객체 변수 instanceof Class-Type
* 다형성
- 객체 지향에서 다향성은 서로 다른 객체가 동일한 메시지에 대하여 서로 다른 방법으로 응답할 수 있는 기능이라고 정의할 수 있다.
- 상속, 객체의 형 변환, 메소드 오버라이딩을 통하여 구현될 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class Am { void callme() { System.out.println("클래스 Am의 callme() 메소드 실행"); } } class Bm extends Am { void callme() { // 상위 클래스의 메소드 오버라이딩 System.out.println("클래스 Bm의 callme() 메소드 실행"); } } class Cm extends Am { void callme() { // 상위 클래스의 메소드 오버라이딩 System.out.println("클래스 Cm의 callme() 메소드 실행"); } } class PolymorphismTest1 { public static void main(String[] args) { Am r = new Am(); // 객체 생성 r.callme(); // 클래스 Am의 callme() 메소드 수행 r = new Bm(); // 상위 클래스의 객체 변수에 하위 클래스 객체를 배정 r.callme(); // 하위 클래스 Bm의 callme() 메소드 수행 r = new Cm(); // 상위 클래스의 객체 변수에 하위 클래스 객체를 배정 r.callme(); // 하위 클래스 Cm의 callme() 메소드 수행 } } | cs |
* 추상화
- 복잡한 문제들 중에 공통적인 부분을 추출하여 추상 클래스로 제공하고, 상속을 이용하여 나머지 클래스들을 하위 클래스로 제공하는 기법이다.
- 추상화의 단계
1단계 : 현실 세계의 문제들이 가지는 공통적인 속성을 추출
2단계 : 공통 속성을 가지는 추상 클래스 작성
3단계 : 추상 클래스의 하위 클래스로 현실 세계의 문제들을 구현
* 추상화 클래스와 추상 메소드
- [형식]
| abstract class 클래스 이름 { // 추상 클래스(이 클래스로부터 객체를 생성할 수 없다.) ...... 클래스에 기술할 수 있는 일반적인 멤버 변수와 메소드 abstract void 추상 메소드 이름(); // 추상 메소드(선언 부분만 기술한다.). // 메소드의 몸체가 없기 때문에 // 끝에 ";"을 붙여야 한다. } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | abstract class Shape { // 추상 클래스 선언 ...... abstract void computeArea(); // 추상 메소드 선언. 선언부만 기술. ...... } public class Circle extends Shape { // 추상 클래스로부터 상속받아 Circle 클래스 생성. ...... void computeArea() { // 추상 메소드를 오버라이딩하여 클래스 고유의 기능을 기술. 실제 원의 면적을 계산하는 기능이 기술됨; } } public class Triangle extends Shape { ...... void computeArea() { // 추상 메소드를 오버라이딩하여 클래스 고유의 기능을 기술. 실제 삼각형의 면적을 계산하는 기능이 기술됨; } } | cs |
* 추상 클래스와 추상 메소드의 오버라이딩을 이용하면 더욱 효율적인 다형성을 구현할 수 있다.
* 인터페이스
- 추상 클래스와 유사하지만, 더 완벽한 추상화를 제공한다.
- 추상 클래스는 추상 메소드 외에 다른 멤버 변수나 일반 메소드를 가질 수 있지만, 인터페이스는 추상 메소드(메소드 선언만 있는)와 상수만을 가질 수 있다.
- 인터페이스를 사용함으로써 완벽한 다중 상속은 아니지만 다중 상속을 흉내낼 수 있다.
- [형식]
| interface 인터페이스 이름 [extends 인터페이스 이름, [인터페이스 이름], ...] { // 인터페이스끼리 상속 관계를 구성할 수 있다. ......상수 선언; ......메소드 선언; } | cs |
a. 인터페이스의 예
| interface Sleeper { // 인터페이스 선언. public long ONE_SECOND = 1000; // 상수 선언. 반드시 초기화해야 한다. public long ONE_MINUTE = 60000; // 메소드 선언. 끝에 ";"을 붙인다. public void wakeup(); } | cs |
b. 인터페이스 상속의 예
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | interface Sleeper { // 인터페이스 Sleeper 선언. public long ONE_SECOND = 1000; public long ONE_MINUTE = 60000; public void wakeup(); } interface Worker { // 인터페이스 Worker 선언. public long WORK_TIME = 8; public void sleep(); } interface People extends Sleeper, Worker { // 두 개의 인터페이스로부터 상속받아 // People 인터페이스 선언. public int MAX = 24; public int MIN = 0; public void work(); } public class InterfaceClass implements People { // People 인터페이스를 포함하는 클래스 작성. ...... public void wakeup() { // 인터페이스 메소드 오버라이딩. ...오버라이딩 } public void sleep() { // 인터페이스 메소드 오버라이딩. ...오버라이딩 } public void work() { // 인터페이스 메소드 오버라이딩. ...오버라이딩 } } | cs |
* 클래스에서 인터페이스를 사용하기 위해서는 implements 예약어를 사용해야 한다.
- 클래스가 인터페이스를 포함하면, 인터페이스에서 선언된 모든 메소드를 오버라이딩 해야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | import java.util.Random; interface IStack { // 인터페이스 선언. public void push(int item); // 두 개의 메소드 선언. public int pop(); } class FixedStack implements IStack { // 인터페이스를 포함한 클래스 작성. private int stack[]; private int tos; FixedStack(int size) { stack = new int[size]; tos = -1; } public void push(int item) { // 인터페이스 메소드 오버라이딩. if(tos==stack.length-1) System.out.println("스택이 꽉 찼음"); else stack[++tos] = item; } public int pop() { // 인터페이스 메소드 오버라이딩. if(tos < 0) { System.out.println("스택이 비었음"); return 0; } else { return stack[tos--]; } } } public class InterfaceTest1 { public static void main(String[] args) { Random r = new Random(); FixedStack mystack1 = new FixedStack(10); // 10개의 요소를 가지는 정수 스택 객체 생성. for(int i=0; i<10; i++) mystack1.push(r.nextInt(10)); // 난수를 발생시켜 스택에 저장. System.out.println("스택 : mystack1"); for(int i=0; i<10; i++) System.out.println(mystack1.pop() + " "); // 스택의 내용 출력. } } | cs |
* 인터페이스도 추상 클래스와 같이 다형성을 구현하는데 사용될 수 있다.
- 추상 클래스를 이용하여 다형성을 구현하는 것과 동일한 형태이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | abstract class Figure1 { // 추상 클래스 선언. abstract void draw(); } interface Shape1 { // 인터페이스 선언. public void computeArea(double a, double b); } class Triangle3 extends Figure1 implements Shape1 { // 추상 클래스와 인터페이스를 포함하는 클래스 작성. void draw() { // 메소드 오버라이딩. System.out.println("삼각형을 그리는 기능"); } public void computeArea(double a, double h) { // 메소드 오버라이딩. System.out.println("삼각형의 넓이 : " + (a * h / 2)); } } class Rectangle3 extends Figure1 implements Shape1 { void draw() { System.out.println("사각형을 그리는 기능"); } public void computeArea(double h, double v) { // 메소드 오버라이딩. System.out.println("사각형의 넓이 : " + (h * v)); } } class Oval3 extends Figure1 implements Shape1 { void draw() { System.out.println("원을 그리는 기능"); } public void computeArea(double r1, double r2) { // 메소드 오버라이딩. System.out.println("원의 넓이 : " + (3.14 * r1 * r2)); } } class Polydraw1 { public void pdraw(Figure1 f) { f.draw(); } public void pcomputeArea(Shape1 s, double a, double b) { s.computeArea(a, b); } } public class InterfaceTest2 { public static void main(String[] args) { Polydraw1 p = new Polydraw1(); Figure1 fg1 = new Triangle3(); Figure1 fg2 = new Rectangle3(); Figure1 fg3 = new Oval3(); Shape1 sp1 = new Triangle3(); // 인터페이스 형의 객체 변수에 Shape1 sp2 = new Rectangle3(); // 클래스의 객체를 배정. Shape1 sp3 = new Oval3(); p.pdraw(fg1); p.pcomputeArea(sp1, 4, 4); // 인터페이스 형의 객체 변수로 메소드 호출. p.pdraw(fg2); p.pcomputeArea(sp2, 4, 4); // 인터페이스 형의 객체 변수로 메소드 호출. p.pdraw(fg3); p.pcomputeArea(sp3, 4, 4); // 인터페이스 형의 객체 변수로 메소드 호출. } } | cs |
☞ 자바 GUI
* AWT(Abstract Window Toolkit)
- 자바 언어에서 제공하는 GUI 패키지.
* AWT 컴포넌트의 단점
- 운영체제가 제공하는 그래픽 컴포넌트와 일대일로 연결되어 작동하여야 하는 부담과 실행되는 시스템에 따라 겉모양이 다르게 보인다.
* 스윙(Swing)
- 썬(Sun)사가 넷스케이프사와 공동으로 개발한 그래픽 툴킷.
- 자바의 표준 클래스인 JFC(Java Foundation Classes)로 제공되고 있으며, JDK에 포함되어 있다.
- 스윙은 AWT와 달리 그래픽을 JVM이 자체적으로 처리한다.
* java.awt 패키지
- GUI 구축을 위한 컴포넌트 클래스 뿐만 아니라 다른 클래스들도 많이 제공한다.
· 컴포넌트 배치와 관련된 클래스 :
BorderLayout, FlowLayout, GridLayout, GridBagLayout, GridBagConstraints, CardLayout
· GUI 구성과 관련된 클래스 :
Button, Label, Canvas, Checkbox, Choice, Scrollbar, Component, List, Menu, TextComponent, TextArea, MenuBar, MenuItem, TextField, CheckboxGroup, CheckboxMenuItem, MenuComponent
· 그래픽 출력과 관련된 클래스 :
Color, Font, FontMetrics, Rectangle, Point, Polygon, Graphics, Image
· 컨테이너 클래스 : Frame, Panel, Window, Container, FileDialog, Dialog
· 기타 클래스 : Insets, Dimension, Toolkit, Event, MediaTracker
* Component 클래스
- 추상 클래스
- 그래피컬 사용자 인터페이스(GUI) 구축에 필요한 많은 하위 클래스를 가지고 있다.
- 약 100여 개의 메소드가 제공된다.
* Container 클래스
- Component 클래스의 하위 클래스로서, 컴포넌트를 담는 쟁반 역할을 한다.
- 사용되는 쟁반 역할을 하는 클래스는 JFrame, JPanel, Applet, JApplet 클래스.
* 응용 프로그램에서 GUI를 구축하기 위해서는 프레임 클래스를 이용한다.
- JFrame 클래스 : Component -> Container -> Window -> Frame -> JFrame 형태로 상속된 클래스
- [형식]
JFrame()
JFrame(String title)
title : 프레임의 제목에 나타낼 문자열
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import javax.swing.*; import java.awt.*; class FirstFrame1 { public FirstFrame1() { // 생성자 JFrame jf = new JFrame("첫 번째 GUI 프로그램"); // 프레임 객체 생성 Container ct = jf.getContentPane(); // 프레임으로부터 판(컨테이너) 생성 JButton jb = new JButton("테스트 버튼"); // 버튼 컴포넌트 생성 ct.add(jb); // 버튼을 판(컨테이너)에 추가 jf.setSize(400, 300); // 프레임 크기 설정 jf.setVisible(true); // 프레임을 화면에 출력 } } public class FrameTest1 { public static void main(String[] args) { new FirstFrame1(); } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import javax.swing.*; import java.awt.*; class FirstFrame3 extends JFrame { // JFrame을 상속하여 클래스 생성 public FirstFrame3() { Container ct = getContentPane(); // 컨테이너 객체 생성 JButton jb = new JButton("테스트 버튼"); ct.add(jb); setTitle("두 번째 GUI 프로그램"); // 프레임의 제목 설정 setSize(400, 300); setVisible(true); } } public class FrameTest2 { public static void main(String[] args) { new FirstFrame3(); } } | cs |
* 컴포넌트들은 그릇 역할을 하는 컨테이너(또는 패널)에 담기게 되며, 자바에서는 컨테이너에 컴포넌트를 배치하는 다양한 방법을 배치 관리자 클래스로 제공한다.
* 컨테이너에 컴포넌트를 수평 방향으로 배치하기.
- [형식]
FlowLayout()
FlowLayout(int align)
FlowLayout(int align, int hgap, int vgap)
※ align : 정렬 방식을 지정하는 상수(LEFT, CENTER, RIGHT)
hgap, vgap : 컴포넌트 사이의 수직, 수평 간격(픽셀값)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import javax.swing.*; import java.awt.*; class FlowLayout1 extends JFrame { public FlowLayout1() { Container ct = getContentPane(); FlowLayout fl = new FlowLayout(FlowLayout.RIGHT, 10, 15); ct.setLayout(fl); for (int i=1; i<=15; i++) ct.add(new JButton("버튼"+i)); setTitle("FlowLayout Test1"); setSize(400, 300); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); } } public class FlowLayoutTest1 { public static void main(String[] args) { new FlowLayout1(); } } | cs |
* 컨테이너에 컴포넌트를 추가할 때 방향을 지정하여 추가하기.
- 지정할 수 있는 방향 : East, West, South, North, Center
- [형식]
BorderLayout()
BorderLayout(int hgap, int vgap)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import javax.swing.*; import java.awt.*; class BorderLayout1 extends JFrame { public BorderLayout1() { Container ct = getContentPane(); BorderLayout bl = new BorderLayout(10, 10); ct.setLayout(bl); ct.add(new JButton("오른쪽 버튼"), BorderLayout.EAST); ct.add(new JButton("왼쪽 버튼"), BorderLayout.WEST); ct.add(new JButton("위쪽 버튼"), BorderLayout.NORTH); ct.add(new JButton("아래쪽 버튼"), BorderLayout.SOUTH); ct.add(new JButton("중앙 버튼"), BorderLayout.CENTER); setTitle("BorderLayout Test1"); setSize(400, 300); setVisible(true); } } public class BorderLayoutTest1 { public static void main(String[] args) { new BorderLayout1(); } } | cs |
* 컨테이너에 컴포넌트를 추가할 때 행과 열을 가진 배열 형태로 배치하기.
- [형식]
GridLayout()
GridLayout(int rows, int cols)
GridLayout(int rows, int cols, int hgap, int vgap)
※ rows, cols : 배치할 행과 열을 지정.
* 그릇 역할을 하는 클래스 : Container, JPanel
- Container 클래스는 JFrame 객체의 getContentPane() 메소드에 의해 생성하여 사용한다.
- JPanel 클래스는 직접 생성하여 사용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | import javax.swing.*; import java.awt.*; class JPanel2 extends JFrame { public JPanel2() { Container ct = getContentPane(); ct.setLayout(new BorderLayout(5,5)); // 컨테이너에 Border 배치 관리자 설정 JPanel jp1 = new JPanel(); // 패널 객체 생성 jp1.setLayout(new GridLayout(5,1)); // 패널에 Grid 배치 관리자 설정 jp1.add(new JRadioButton("Java")); // 패널에 컴포넌트 추가 jp1.add(new JRadioButton("C")); jp1.add(new JRadioButton("Visual Basic")); jp1.add(new JRadioButton("JSP")); jp1.add(new JRadioButton("PHP")); JPanel jp2 = new JPanel(); // 패널 객체 생성 jp2.setLayout(new GridLayout(5,1)); // 패널에 Grid 배치 관리자 설정 jp2.add(new JButton("Java")); // 패널에 컴포넌트 추가 jp2.add(new JButton("C")); jp2.add(new JButton("Visual Basic")); jp2.add(new JButton("JSP")); jp2.add(new JButton("PHP")); ct.add(jp1, BorderLayout.EAST); ct.add(jp2, BorderLayout.WEST); setTitle("JPanel Test2"); setSize(300,200); setVisible(true); } } public class JPanelTest2 { public static void main(String[] args) { new JPanel2(); } } | cs |
* 이벤트(event)
- 사용자의 입력, 즉 키보드, 마우스 등의 장치로부터 발생하는 모든 사건을 의미한다.
* 이벤트 지향(event-driven) 프로그램
- 프로그램은 무한 루프를 돌면서 사용자의 이벤트가 발생하기를 기다린다.
- 이벤트가 발생하면, 그 이벤트를 처리하고 다시 무한 루프에 빠지게 된다.
* 위임형 이벤트 모델(delegation event model)
- 자바의 이벤트 처리 모델
- 컴포넌트에 등록된 이벤트가 발생하면 리스너를 호출한다.
* 자바에서의 대부분의 이벤트는 GUI 관련 컴포넌트에서 발생한다.
- JComponent ┬ AbstractButton ┬ JMenuItem ┬ JCheckBoxMenuItem
│ │ │ JMenu
│ │ └ JRadioButtonMenuItem
│ ├ JButton
│ └ JToggleButton ┬ JCheckBox
│ └ JRadioButton
├ JComboBox
├ JLabel
├ JMenuBar
├ JPanel
├ JScrollPane
├ JTabbedPane
├ JTextComponent ┬ JTextArea
│ └ JTextField
├ JTable
└ JTree
* 자바에서는 이벤트를 객체로 처리한다.
* 자바에서는 이벤트와 연관된 클래스들을 java.awt.event 패키지로 제공한다.
* 자바 가상 기계(JVM)의 이벤트 전달
- JVM은 컴포넌트에 등록된 이벤트가 발생하면 관련 이벤트 클래스로부터 객체를 생성하여 리스너를 호출한다.
- 리스너는 전달받은 이벤트 객체를 이용하여 이벤트를 처리한다.
* EventObject 클래스
- 대부분의 주요 이벤트 클래스들이 EventObject 클래스로부터 상속된다.
- [형식]
EventObject(Object src)
※ src : 이벤트를 생성하는 객체.
* AWTEvent 클래스
- EventObject 클래스로부터 상속된 클래스이다.
int getID() : 이벤트의 형을 반환한다.
* Action 이벤트
- 버튼이 눌려졌거나, 리스트 항목이 선택되었을 때, 메뉴의 한 항목이 선택되었을 때 발생한다.
- 가장 많이 사용되는 이벤트 클래스이다.
- [형식]
ActionEvent(Object src, int type, String cmd)
ActionEvent(Object src, int type, String cmd, int modifiers)
※ src : 이벤트를 발생한 객체.
type : 이벤트의 타입.
cmd : 이벤트를 발생시킨 컴포넌트의 레이블.
modifiers : 이벤트가 발생할 때 같이 사용된 수정키를 의미하는 상수.
* 수정자(modifier) 키를 구분하기 위한 상수
- ALT_MASK : 수정자 키로 ALT 키를 사용.
- CTRL_MASK : 수정자 키로 CTRL 키를 사용.
- META_MASK : 수정자 키로 META 키를 사용.
- SHIFT_MASK : 수정자 키로 SHIFT 키를 사용.
* Adjustment 이벤트
- 스크롤 바의 위치가 이동되면 발생한다.
- BLOCK_DECREMENT : 스크롤 바의 값을 감소시키는 경우.
- BLOCK_INCREMENT : 스크롤 바의 값을 증가시키는 경우.
- TRACK : 스크롤 바를 드래그(drag)하는 경우.
- UNIT_DECREMENT : 스크롤 바의 값을 하향 버튼을 사용하여 감소시키는 경우.
- UNIT_INCREMENT : 스크롤 바의 값을 상향 버튼을 사용하여 증가시키는 경우.
* ItemEvent
- 체크박스나 리스트 항목이 선택되었을 때 또는 메뉴의 한 항목이 선택되었거나 선택된 항목이 해제될 때 발생한다.
- SELECTED : 한 항목이 선택되었을 때.
- DESELECTED : 선택된 항목이 해제되었을 때.
* KeyEvent, MouseEvent 등등
* 이벤트 리스너 인터페이스를 이용하여 이벤트를 처리하기 위한 순서
1. 처리할 이벤트의 종류를 결정한다.
2. 이벤트에 적합한 이벤트 리스너 인터페이스를 사용하여 클래스를 작성한다.
3. 이벤트를 받아들일 각 컴포넌트에 리스너를 등록한다.
예) addActionListener(ActionListener l)
addItemListener(ItemListener l)
addKeyListener(KeyListener l)
addMouseListener(MouseListener l) 등
※ 리스너 제거는 add 대신 remove.
4. 리스너 인터페이스에 선언된 메소드를 오버라이딩하여 이벤트 처리 루틴을 작성한다.
* ava.awt.event 패키지
- 각각의 이벤트 클래스와 연관된 이벤트 리스너 인터페이스를 제공한다.
* 자바에서는 다양한 방법으로 이벤트를 처리할 수 있다.
1. GUI를 제공하는 클래스에서 직접이벤트를 처리하는 방법
2. 이벤트 처리를 위한 클래스를 따로 만들어 사용하는 방법
3. 내부 클래스를 사용하여 이벤트를 처리하는 방법
4. 무명(anonymous) 클래스를 이용하는 방법
5. 람다식(Java 1.8)을 이용하는 방법
* GUI를 제공하는 클래스 내에서 처리하는 방법
1. 처리가 요구되는 이벤트를 결정한다.
2. 관련된 리스너 인터페이스를 포함하여 클래스를 작성한다.
3. 인터페이스에 선언된 메소드를 오버라이딩하여 이벤트 처리 루틴을 작성한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import javax.swing.*; import java.awt.*; import java.awt.event.*; class Event1 extends JFrame implements ActionListener { // 버튼에 동작하는 이벤트를 처리하기 위해 ActionListener를 포함. JLabel jl; // JLabel 객체를 속성으로 등록. public Event1() { Container ct = getContentPane(); ct.setLayout(new FlowLayout()); JButton jb = new JButton("버튼"); // 버튼 객체 생성. jl = new JLabel("버튼을 누르세요."); // 라벨 객체 생성. jb.addActionListener(this); // 버튼 객체에 리스너를 등록. // (this는 자체 처리를 의미.) ct.add(jb); ct.add(jl); setTitle("Event Test1"); setSize(200, 100); setVisible(true); } public void actionPerformed(ActionEvent e) { // 이벤트 처리 메소드 작성. jl.setText("잘 하셨어요."); // 라벨의 값을 새로운 값으로 설정. } } public class EventTest1 { public static void main(String[] args) { new Event1(); } } | cs |
오늘도 수고하셨습니다!