연락처를 파일로 관리하고, JTable을 이용해 출력한다.
이 프로그램은 대학교 2학년 JAVA 프로그래밍 강의에서 과제로 했던 주소록 관리 프로그램이다.
Java를 이 강의에서 처음 접했었고, 이 과제를 해결했을 당시에는 Java 언어도 잘 알지 못했고 GUI도 배운 지 2~3주 차 정도 되었을 때였기 때문에 데이터 효율, 가독성 등은 고려하지 않고 오직 구현에만 집중하였다. 전반적으로 실력이 부족했었던 것 같다.
이후에 기회가 된다면 다른 기능들을 추가해가며 업그레이드 해보려고 한다.
아래와 같이 AddressGUI라는 java class 파일을 만들고, AddressTest의 main에서 실행하는 단순한 구조로 만들었다.
public AddressGUI()
부터 static void refreshData()
까지 2번~8번을 끼워넣으면 된다.public class AddressGUI extends JFrame {
static String fname = "data/juso.txt";
static JLabel nameTxt,studentNumTxt,ageTxt,birthTxt,phoneTxt;
static JTextField nameSpace,studentNumSpace,ageSpace,birthDaySpace,phoneSpace,delName;
static JTable table;//연락처 출력할 JTablestatic String[][] data = new String[50][5];
static String[] colNames = {"이름","나이","생일","학번","전화번호"};
public AddressGUI() {}//(2)GUI 화면 구성과 버튼 액션 등 구현
static class Address{}//(3)add_juso에서 사용할 클래스
static void view_juso()//(4)연락처 출력 메서드
static void add_juso()//(5)연락처 파일에 데이터추가 메서드
static void delete_juso()//(6)데이터 삭제 메서드
static void tableRefresh()//(7)JTable을 갱신해 주는 메서드
static void refreshData()//(8)화면 출력 전, 출력을 위한 데이터를 refresh해주기 위한 메서드
}
public class AddressTest {
public static void main(String[] args) {
new AddressGUI();
}
}
public AddressGUI() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//종료버튼
setTitle("연락처 관리");// 제목 설정
setResizable(false);
this.setLayout(null);
//panel1(2-1) : 맨 윗줄 - 연락처출력 / 나가기 / 연락처 삭제
//panel2(2-2) : 두번째 줄 - 연락처 입력 받아서 등록
//panel3(2-3) : JTable - 연락처를 table 형식으로 출력
setSize(850,280);// 윈도우 크기설정
setVisible(true);// 윈도우가 화면에 보임
}
// Panel1
JPanel panel1 = new JPanel();
panel1.setLayout(new FlowLayout());
//연락처 출력 버튼
JButton printBtn = new JButton("연락처 출력");
printBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
view_juso();
} catch (IOException e) {
e.printStackTrace();
}
}
});
panel1.add(printBtn);
//나가기 버튼
JButton exitBtn = new JButton(" 나가기 ");
exitBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
panel1.add(exitBtn);
//연락처 삭제 버튼, label
JLabel deleteAddress = new JLabel(" 삭제할 연락처(이름) : ");
panel1.add(deleteAddress);
delName = new JTextField(5);
panel1.add(delName);
JButton delete = new JButton("연락처 삭제");
delete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
delete_juso();
refreshData();
tableRefresh();
} catch (IOException e) {
e.printStackTrace();
}
}
});
panel1.add(delete);
//panel 위치 설정
panel1.setBounds(10,10,850,40);// (x축, y축, 폭, 높이)this.add(panel1);//setBounds로 정한 위치에 panel1 추가
//panel2 : 입력창
JPanel panel2 = new JPanel();
panel2.setLayout(new FlowLayout());
//label, TextField 배치
nameTxt = new JLabel(" 이름");panel2.add(nameTxt);
nameSpace = new JTextField(5);panel2.add(nameSpace);
ageTxt= new JLabel(" 나이");panel2.add(ageTxt);
ageSpace = new JTextField(3);panel2.add(ageSpace);
birthTxt= new JLabel(" 생일");panel2.add(birthTxt);
birthDaySpace = new JTextField(10);panel2.add(birthDaySpace);
studentNumTxt= new JLabel(" 학번");panel2.add(studentNumTxt);
studentNumSpace = new JTextField(8);panel2.add(studentNumSpace);
phoneTxt = new JLabel(" 전화번호");panel2.add(phoneTxt);
phoneSpace = new JTextField(12);panel2.add(phoneSpace);
//연락처 등록 버튼
JButton regist = new JButton("연락처 등록");
regist.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
try {
add_juso();
refreshData();
tableRefresh();
} catch (IOException e) {
e.printStackTrace();
}
}
});
panel2.add(regist);
//panel2 위치 설정
panel2.setBounds(10,50,850,50);
this.add(panel2);
//panel3 : 테이블
JPanel panel3 = new JPanel();
//연락처를 출력할 table 설정
table = new JTable(data,colNames);
JScrollPane sp = new JScrollPane(table);//scrollPane 에 테이블 위치시킴
table.setFillsViewportHeight(true);// scrollPane 안에 테이블을 꽉 차서 보이게 함
Dimension d = table.getPreferredSize();//d에서 설정한 사이즈를 넘어갈 시 스크롤바가 생성되도록 설정
d.width = 700;
d.height = 120;
sp.setPreferredSize(d);//스크롤바 생성
panel3.add(sp);
panel3.setBounds(0,100,850,200);
this.add(panel3);
static class Address {
String name;
String age;
String birthDay;
String studentNum;
String phone;
Address(String s1, String s2, String s3, String s4, String s5){
this.name=s1;
this.age=s2;
this.birthDay=s3;
this.studentNum=s4;
this.phone=s5;
}
}
static void view_juso() throws IOException{//file 다룰때는 throws IOException 꼭 써주기
File f = new File(fname);//파일 생성//파일이 존재하지 않을때if(!f.exists()) {
BufferedWriter bw = new BufferedWriter(new FileWriter(fname));//파일을 쓰기 모드로 염
bw.close();//바로 닫아줌
}
refreshData();// 파일을 읽어와서 데이터에 다시 저장해주는 메소드
tableRefresh();//table을 refresh 해주는 메소드
}
에러메시지 출력 방법
에러가 없다면 wstr에 양식에 맞춰 파일에 넣을 문자열을 생성하고, 파일에 써줌
static void add_juso() throws IOException{
Address adr = new Address("","","","","");
String msg1="",msg2="",msg3="",msg4="",msg5="",msg6="";//에러뜨면 에러메시지에 추가할 문자열
String error="";//위의 문자열중에 해당하는것만 error에 추가해줄
String wstr = "";
BufferedWriter bw = new BufferedWriter(new FileWriter(fname,true));
String nameExp = "^[가-힣]*$|^[a-zA-Z]*$";//이름 pattern (형식) 포맷
String phoneExp = "(02|010)-\\d{3,4}-\\d{4}";//폰번호 포맷
String birthDayExp = "\\d{4}-\\d{2}-\\d{2}";//생일 포맷
adr.name = nameSpace.getText();
if(!Pattern.matches(nameExp, adr.name)){//패턴이 맞는지 확인하는 메소드
msg1="이름에는 한글 또는 영어만 입력 가능합니다.\n";
}
//왠지 모르겠지만 에러 뜸(integer는 Pattern,matches가 안되는듯?) 그래서 age만 ageCheck로 체크함int ageCheck=0;
adr.age = ageSpace.getText();
if(adr.age.trim().isEmpty()) {//trim() : 공백 제거 , isEmpty() : 비어있으면 true
ageCheck=1;
}else if(Integer.parseInt(adr.age)>200) {
msg2="나이는 200살을 넘을 수 없습니다.\n";
}
adr.birthDay = birthDaySpace.getText();
if(!Pattern.matches(birthDayExp, adr.birthDay)){
msg3 = "생일은 (ex.1998-01-01)형식으로 입력해주세요.\n";
}
adr.studentNum = studentNumSpace.getText();
adr.phone = phoneSpace.getText();
if(!Pattern.matches(phoneExp, adr.phone)){
msg5 = "전화번호는 (ex.010-1234-5678)형식으로 입력해주세요\n";
}
if(adr.name.trim().isEmpty()||(ageCheck==1)||adr.birthDay.trim().isEmpty()||adr.studentNum.trim().isEmpty()||adr.phone.trim().isEmpty()) {
msg6 = "\n!!!!!!!빈칸이 있습니다.!!!!!!!\n";
}//공백이 하나라도 있으면 맨 아래에 빈칸있다고 알려줌
if((msg1!="")||(msg2!="")||(msg3!="")||(msg4!="")||(msg5!="")||(msg6!="")) {
error = msg1+msg2+msg3+msg4+msg5+msg6;
//에러 뜬 부분은 위에서 msg1~6에 저장했음. error 변수에 다 합쳐줌
JOptionPane errorMsg=new JOptionPane();//에러메시지 출력해주는 클래스
errorMsg.showMessageDialog(null, error);
return;//에러 발생시 return 해줌
}else {//wstr : 전체 문자열에 tab으로 구분하며 저장
wstr = adr.name + "\t" + adr.age + "\t" + adr.birthDay
+ "\t" + adr.studentNum+ "\t" + adr.phone;
nameSpace.setText("");
ageSpace.setText("");
birthDaySpace.setText("");
studentNumSpace.setText("");
phoneSpace.setText("");
}
bw.write(wstr);//wstr 문자열을 bw에 써줌
bw.newLine();//다쓰고 newLine()해줘서 다음에 쓸때 다음줄부터 시작
bw.close();
}
static void delete_juso() throws IOException{
int i,count=0;
String str;
String[] read_str = new String[50];
BufferedReader br = new BufferedReader(new FileReader(fname));
// 연락처 파일이 없으면 returnif(!br.ready()) {
return;
}
String del = delName.getText();//삭제할 이름 getText 해서 del 에 저장
String del_PopUpMsg = del+"의 연락처가 삭제되었습니다.";//삭제 됬을때 팝업 메시지
//del이 비어있을때 는 에러메시지 출력하고 returnif(del.trim().isEmpty()) {
JOptionPane cc=new JOptionPane();
cc.showMessageDialog(null,"삭제할 이름을 입력해주세요.");
br.close();
return;
}else {
for(i=0;i<50;i++) {
str = br.readLine();//지역변수 str에 파일 한줄씩 읽어와서 저장if(str==null)break;//읽을 줄이 없으면 break
//str이 지우고자 하는 이름으로 시작하지 않으면 ( 삭제하고싶은 이름이 아닐때 )if(!str.startsWith(del)) {
read_str[count]=str;//read_str[] 배열에 하나씩 저장해주고
count++;//count는 처음에 0이고 한줄씩 저장할때마다 ++ 해줌
}else {//str이 지우고자 하는 이름으로 시작하면 삭제했다는 메시지 출력
JOptionPane bb=new JOptionPane();
bb.showMessageDialog(null,del_PopUpMsg);
}
}
}
br.close();
//위에서 read_str[] 배열에 전체 연락처 문자열이 하나씩 다 저장되어있음
BufferedWriter bw = new BufferedWriter(new FileWriter(fname));
//read_str에 저장된것을 파일에 다시 써줌for(i=0;i<count;i++) {
bw.write(read_str[i]);
bw.newLine();//read_str 써주고 다음줄에 다시 써줌
}
bw.close();
delName.setText("");
}
=> 이 메소드가 실행되면 JFrame의 table이 갱신됨
static void tableRefresh() {
DefaultTableModel model = new DefaultTableModel(data,colNames);
table.setModel(model);
}
출력하기 직전에 JTable에 출력하기위한 배열 data[50][5]에 연락처 정보를 갱신
화면에 출력하려면 전역변수 data에 연락처 정보가 저장되어있어야 됨
static void refreshData()throws IOException {
int i,j;
//data[50][5]를 비워줌for(i=0;i<50;i++) {
for(j=0;j<5;j++) {
data[i][j]="";
}
}
BufferedReader br = new BufferedReader(new FileReader(fname));
String str;//파일을 읽어와서 모든 정보를 포함한 한줄의 연락처 문자열을 저장
String[] personal = new String[5];// 한사람의 이름/나이/생일/학번/연락처 이렇게 5개를 저장할 String 배열
//기존의 파일을 모두 읽어서 data[][]에 저장
for(i=0;;i++) {
if(!br.ready())break;//파일을 읽을 수 없으면 break
else {
str=br.readLine();//str에 파일에서 읽어온 한 줄의 문자열을 저장
personal = str.split("\t");//personal[5] 배열에 \t를 기준으로 분리해서 저장
data[i] = personal;//data[0][] , data[1][] ...(2차원 배열) 에 하나씩 personal[5](1차원배열)을 저장
}
}
br.close();
}