반응형
- GUI프로그램도 파일 입출력을 할 수 있다! 의 초점맞춰서 코드 확인하기
1) 기본
package xyz.itwill.io;
import java.awt.BorderLayout;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.KeyStroke;
//텍스트 파일 편집기 프로그램 - 메모장
//🌈디자인클래스
public class NotepadApp extends JFrame implements ActionListener{
2) 필드
private static final long serialVersionUID = 1L;
//🍀JMenuItem 컴포넌트를 선택한 경우 ActionEvent 발생
private JMenuItem init, open, save, exit;
private JTextArea area;
//🌈FileDialog : 파일을 선택하기 위한 다이알로그를 생성하기 위한 컴퍼넌트
private FileDialog openDialog, saveDialog;
//현재 작업중인 문서파일의 경로를 저장하기 위한 필드
private String filePath;
//☝JTextArea 컴포넌트의 내용 변경 상태를 저장하기 위한 필드 - 문서파일 변경 유무 확인
//=> false : (작업중인 문서파일) 미변경 , true: (작업중인 문서파일) 변경
private boolean status;
3) 생성자
public NotepadApp(String title) {
super(title);
//🌈메뉴바만들기
JMenuBar bar = new JMenuBar();
JMenu menu = new JMenu("파일(F)");
menu.setMnemonic('F');
init = new JMenuItem("새로 만들기(N)", 'N');
open = new JMenuItem("열기(O)", 'O');
save = new JMenuItem("저장(S)", 'S');
exit = new JMenuItem("끝내기(X)", 'X');
init.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK));
open.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK));
save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
menu.add(init);
menu.add(open);
menu.add(save);
menu.addSeparator();
menu.add(exit);
bar.add(menu);
setJMenuBar(bar);
//🌈메모장만들기
area = new JTextArea();
area.setFont(new Font("굴림체", Font.PLAIN, 20));
JScrollPane pane = new JScrollPane(area);
getContentPane().add(pane, BorderLayout.CENTER);
//🐣이벤트발생 시 이벤트 처리 객체 등록
init.addActionListener(this);
open.addActionListener(this);
save.addActionListener(this);
exit.addActionListener(this);
//🐣키보드 이벤트를 만들어 키보드를 누르는 행위가 일어날 시에(문서가 편집될 시에)!!!!!!!!! 키보드를 눌렀다는 상태 변경 + 프레임의 제목 변경이 될 수 있도록 만듦
//🐣JtextArea 컴포넌트에서 키보드 관련 이벤트가 발생된 경우 실행될 이벤트 처리 객체 등록
// => KeyAdapter클래스를 상속받은 익명의 자식클래스의 객체를 이용하여 이벤트 처리
// => (KeyEventListener인터페이스의 추상메소드 3개 중 keyTyped()만 사용할 예정이기 때문)
area.addKeyListener(new KeyAdapter() {
//키보드를 눌렀다 띄었을 때 자동 호출되는 이벤트 처리 메소드
@Override
public void keyTyped(KeyEvent e) {
//KeyEvent.getKeyChar() : 이벤트가 발생된 키보드의 문자값을 반환하는 메소드
if(!status && e.getKeyChar()!='\\0') { //이벤트가 발생된 키보드의 문자값이 NULL 문자가 아닌 경우
status = true; //상태변경 (현재 작업중인 문서가 변경되었어요~)
setTitle("*"+getTitle()); //프레임의 제목 변경
}
}
});
//🍀읽기 파일을 선택하기 위한 파일 다이얼로그 생성 - 열기용
openDialog = new FileDialog(this, "열기", FileDialog.LOAD); //눈에 보이지는 않음
//🍀쓰기 파일을 선택하기 위한 파일 다이얼로그 생성 - 저장용
saveDialog = new FileDialog(this, "저장", FileDialog.SAVE);
//🌈프레임 기본 틀 만들기 + 닫기버튼
//setDefaultCloseOperation(EXIT_ON_CLOSE);
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); //닫기버튼눌러도 실행 안됨
//프레임에서 닫기 버튼을 누른 경우 실행될 이벤트 처리 객체 등록
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
if(!saveComfirm()) return; // "너 저장할꺼야?"창 질문
System.exit(0);
}
});
setBounds(450,150,1000,600);
setVisible(true);
}
4) 메인메소드
//main메소드
public static void main(String[] args) {
new NotepadApp("제목 없음 - Java 메모장");
}
5) 오버라이드 선언된 actionPerformed
//🍀오버라이드선언된 actionPerformed
@Override
public void actionPerformed(ActionEvent e) {
//1.
//이벤트발생 객체 가져오기
Object eventSource = e.getSource();
//2.
//이벤트발생 객체에 따른 이벤트처리메소드 작성하기
//2-1.
if(eventSource == init) {
//선택 다이얼로그에서 저장 유무 선택할 수 있도록 선택 다이얼로그를 닫거나 [취소]를 선택한 경우 이벤트 처리 메소드 종료
if(!saveComfirm()) return; // "너 저장할꺼야?"창 질문
filePath = null;//문서 파일의 경로 초기화
area.setText("");//JTextArea컴포넌트 초기화
setTitle("제목없음 - Java메모장");//프레임 제목 변경
//2-2.
}else if(eventSource == open) {
if(!saveComfirm()) return; // "너 저장할꺼야?"창 질문
//열기 관련 파일 다이얼로그를 화면에 출력
// => 파일을 선택하거나 선택을 취소한 경우 파일 다이얼로그는 자동으로 숨김 처리 - 메모리에서 없어지는 것은 아님
openDialog.setVisible(true);
//FileDialog.getFile() : 선택된 파일을 반환하는 메소드
// => 파일 다이얼로그에서 파일 선택을 취소한 경우 이벤트 처리 메소드 종료
if(openDialog.getFile()==null) return;
//FileDialog.getDirectory() : 선택된 파일이 저장된 디렉토리 경로를 반환하는 메소드
// => 파일 다이얼로그에서 선택된 파일에 대한 시스템 경로를 반환받아 저장
filePath = openDialog.getDirectory() + openDialog.getFile();
try {
//파일 입력스트림을 생성하여 저장 (문자단위로 입력 - 2Byte)
BufferedReader in = new BufferedReader(new FileReader(filePath));
//프레임의 제목 변경
setTitle(openDialog.getFile() + " - Java 메모장");
area.setText(""); //JTextArea 컴포넌트 초기화
//파일에 저장된 값을 한줄씩 읽어 JTextArea 컴포넌트에 출력 처리함
while(true) {
//파일 입력스트림에서 엔터(Enter)전까지의 모든 문자데이타(문자열)를 읽어 저장
String text = in.readLine(); //BufferedReader를 통한 메소드 호출
//읽어들일 문자열이 더 이상 없는 경우 반복문 종료
//문자가 아닌 문자열!! 만약 문자였다면 if(readByte = -1)
if(text==null) break;
//JTextArea 컴퍼넌트에 문자열을 추가하여 출력
area.append(text+"\\n"); //load하다.
}
in.close();
//JTextArea.setCaretPosition(int position) : JTextArea 컴포넌트의 입력촛점(커서)의 위치를 변경하는 메소드
area.setCaretPosition(0); //입력촛점을 처음위치로 이동
} catch (FileNotFoundException exception) {
JOptionPane.showMessageDialog(this, "선택한 파일을 찾을 수 없습니다.");
} catch (IOException exception) {
JOptionPane.showMessageDialog(this, "파일을 open하는 중에 프로그램에 문제가 발생 하였습니다.");
}
//2-3.
//저장 버튼 누를 경우 매번 새로운이름으로 저장되니 참조변수에 파일경로를 만드는 것이 아닌, 필드에 파일경로를 만들어서 파일경로에 현재파일경로를 저장해 사용하자
}else if(eventSource == save) {
//현재 작업 중인 문서파일이 없는 경우 - 파일다이얼로그를 눈에 보이게 한 뒤, 파일을 선택해 저장하도록
//작업 중인 파일이 있다면 아래 명령은 생략됨
if(filePath == null) {
//저장 관련 파일 다이얼로그를 화면에 출력
saveDialog.setVisible(true);
//파일 다이얼로그에서 파일 선택을 취소한 경우 이벤트 처리 메소드 종료
if(saveDialog.getFile()==null) return;
//파일 다이얼로그에서 선택된 파일에 대한 시스템 경로를 반환받아 저장
filePath = saveDialog.getDirectory() + saveDialog.getFile();
//프레임의 제목 변경
setTitle(saveDialog.getFile() + " - Java 메모장");
}
try {
//파일 출력스트림을 생성하여 저장
BufferedWriter out = new BufferedWriter(new FileWriter(filePath));
//JTextArea 컴포넌트의 모든 문자열을 반환받아 저장
String text = area.getText();
//BufferedWriter.write(String s) : 출력스트림의 문자열을 전달하는 메소드
out.write(text);
out.close(); //파일 출력스트림 닫기
status = false; //저장 상태 변경
setTitle(getTitle().substring(1)); //프레임 제목 변경 , substring(1):별제거
} catch (IOException exception) {
JOptionPane.showMessageDialog(this, "파일을 save하는 중에 프로그램에 문제가 발생 하였습니다.");
}
//2-4.
}else if(eventSource == exit) {
if(!saveComfirm()) return; // "너 저장할꺼야?"창 질문
System.exit(0);
}
}
// "너 저장할꺼야?"창 질문
// => JTextArea 컴포넌트 내용 변경에 따른 저장 유무를 선택하여 처리하기 위한 메소드
// => 선택 다이알로그를 이용하여 저장 유무를 선택하여 처리
// => 반환값 - false : (아무런 동작하지 않으면 됨) 선택 다이알로그의 [창닫기] 또는 [취소]
// => 반환값 - true : 선택 다이알로그의 [저장] :파일처리 또는 [미저장]:파일미처리
// => [새로 만들기], [열기], [끝내기]의 JMenuItem 컴포넌트를 선택한 경우 호출되는 메소드
public boolean saveComfirm() {
//JTextArea 컴포넌트 내용 변경이 발생한 경우
if(status) {
//1.
//JOptionPane.showConfirmDialog(Component parent, String message, String title, int optionType) : 선택 다이알로그를 출력하는 메소드 - 선택값 반환
int choice = JOptionPane.showConfirmDialog(this, "변경된 내용을 저장 하시겠습니까?", "확인", JOptionPane.YES_NO_CANCEL_OPTION);
//2.
//선택 다이얼로그의 선택에 의해 명령을 구분하여 실행
//2-1.
//"YES" 옵션을 선택한 경우 - [저장]
if(choice == JOptionPane.YES_OPTION) {
if(filePath == null) {
saveDialog.setVisible(true);
if(saveDialog.getFile()==null) return false;
filePath = saveDialog.getDirectory() + saveDialog.getFile();
setTitle(saveDialog.getFile() + " - Java 메모장");
}
try {
BufferedWriter out = new BufferedWriter(new FileWriter(filePath));
String text = area.getText();
out.write(text);
out.close();
} catch (IOException exception) {
JOptionPane.showMessageDialog(this, "파일을 save하는 중에 프로그램에 문제가 발생 하였습니다.");
}
//2-2.
//"창닫기" 또는 "CANCEL" 옵션을 선택한 경우 - [취소]
}else if(choice == JOptionPane.CLOSED_OPTION || choice == JOptionPane.CANCEL_OPTION) {
return false;
}
}
//선택 다이얼로그에서 "YES" 또는 "NO" 옵션을 선택한 경우 - [저장] 또는 [미저장]
status = false; //변경 상태 초기화
return true;
}
}
반응형
'java > java.io' 카테고리의 다른 글
[java.io] 4. 객체 직렬화(Object Serialization) 클래스 (1) | 2024.07.01 |
---|---|
[java.io] 3. Data보조스트림 | Object보조스트림 (1) | 2024.06.30 |
[java.io] 2. File(파일)클래스 (0) | 2024.06.30 |
[java.io] 1. 입출력스트림(원시데이타기반 | 문자데이타기반) (0) | 2024.06.30 |