데이터 매니저에 GUI 연결하기(1단계)
1단계: 노래 데이터를 JLabel에 보여주고 검색, 수정, 삭제 기능 제공
2단계: 노래 데이터를 JTable에 보여주고 검색, 수정, 추가, 삭제 기능 제공
3단계: 파사드 패턴을 이용해서 재사용가능한 JTable 기능 제공
앞에서 살펴본 Manager와 Manageable, 그리고 제너릭으로 구현된 SongMgr 클래스를 이용하여 다음과 같이 입력파일에서 입력 받아 Song 클래스 객체를 만들어 관리자가 관리하는 프로그램을 만들 수 있다.
다음은 콘솔 화면에서 파일 입력과 출력을 하는 클래스를 보여준다.
public class SongConsoleMain extends Manager<Song> {
public SongConsoleMain() {
readAllSongs("songs.txt");
}
void readAllSongs(String filename) {
super.readAll(filename, new Factory<Song>() {
public Song create() {
return new Song();
}
});
}
public static void main(String[] args) {
SongConsoleMain engine = new SongConsoleMain();
engine.printAll();
}
}
여기서 Manager<Song>은 readAll, printAll 기능을 제공하는 제너릭 클래스를 Song으로 인스턴스화한 타입이다. https://plas.tistory.com/49 참고.
이것을 다음과 같이 GUI에 연결하여 화면에 보여주는 방법을 생각해 보자.
우리는 위와 같은 Manager<Song>이 가진 정보를 화면에 보여주고 싶다. 또한 검색이나 수정, 삭제 등의 연산이 Manager<Song> 이 가진 리스트와 화면에 보여지는 정보가 일치되기를 원한다. 이런 경우 우리는 Manager<Song>과 그것을 처리하는 콘솔 프로그램 부분을 엔진레이어라고 하고 화면에 보여주는 기능을 제공하는 부분을 GUI 레이어라고 부를 수 있다.
이러한 GUI를 제공하기 위해서는 엔진과 GUI 레이어에서 다음과 같은 기능을 제공해야 한다.
- 가운데 JLabel 창에 Song 리스트의 정보를 보여줄 수 있어야 한다.
- 검색: 키워드를 받아와서 검색된 Song만 리스트를 보여줄 수 있어야 한다.
- 수정, 삭제 기능을 GUI의 요청에 따라 엔진에 반영한 후 화면을 업데이트해야 한다.
- 수정은 번호의 곡의 제목을 변경하는 것이고 삭제 버튼은 해당 번호의 곡을 삭제한다.이
이러한 기능을 구현하기 위해 위의 SongConsoleMain 클래스에 다음과 같은 기능이 추가되어야 한다. 이것을 SongMgr 클래스라고 하자.
public List<Song> search(String kwd) {
if (kwd == null)
return mList;
return findAll(kwd);
}
public void update(int n, String title) {
// TODO Auto-generated method stub
Song s = find(""+n);
s.set(title);
}
public void removeAt(int num) {
// TODO Auto-generated method stub
Song s = find(""+num);
mList.remove(s);
}
여기서 findAll이나 find는 Manager<T>에서 제공하는 기능이다. mList도 Manager<T>의 필드인데 이것도 메소드를 통해 제공하면 더 좋을 것이다. Song 클래스에서 제목 수정 기능을 위해 set 메소드를 제공해야 함을 알 수 있다.
이들 메소드는 GUI 레이어에서 버튼의 액션 핸들러에서 불려질 것이다. 이제 위의 화면을 제공하는 GUI 클래스들을 살펴보자.
GUIMain
이 클래스는 일반적인 스윙 프로그램처럼 JFrame을 상속하고 SongListPanel 클래스 객체를 이용해서 컨텐츠 페인을 채우고 있다.
SongListPanel
이 클래스가 화면의 내용을 구성하게 되는데, 상부의 검색 창을 JPanel, 가운데는 JScrollPane으로 스크롤을 가지는 패널로 넣고 아래는 bottom이라는 이름의 JPanel을 상속한 BottomPane 클래스를 이용해 만들고 있다. addComponentsToPane 메소드에서 구성요소를 만들어 추가하는데, 중간에 들어가는 노래의 정보를 가질 객체를 songListLabel이라고 하는 JLabel을 이용한다.
이 클래스의 loadData 메소드가 검색 키워드에 의한 리스트를 받아와서 JLabel에 텍스트로 붙여넣는 역할을 한다.
void loadData(String kwd) {
List<Song> findList = GUIMain.engine.search(kwd);
String text = "<html><body>";
for (Song s: findList)
text += s + "<br/>";
songListLabel.setText(text);
}
여기서 엔진 레이어의 search 함수를 이용하여 검색된 리스트를 받아오는 것을 알 수 있다. 그리고 각 Song 객체는 toString을 통해 제공되는 스트링으로 변환되어 songListLabel에 보여질 스트링 text에 붙여지게 된다. 마지막에 setText를 통해 해당 문자열을 JLabel에 보여준다.
BottomPane
다음으로 BottomPane 클래스는 하단의 텍스트 필드와 버튼을 추가하여 화면을 구성하고 버튼에 대한 액션 핸들러를 제공하는 클래스다.
public void actionPerformed(ActionEvent e) {
int n = Integer.parseInt(numField.getText());
switch (e.getActionCommand()) {
case "수정":
GUIMain.engine.update(n, edit.getText());
parent.loadData("");
break;
case "삭제":
GUIMain.engine.removeAt(n);
parent.loadData("");
break;
default: break;
}
}
이와 같이 수정과 삭제는 각각 엔진인 SongMgr 클래스의 update와 removeAt을 호출하고 있다.
전체 코드는 아래 파일에서 찾을 수 있다. (입력파일 songs.txt 포함)