[Java GUI]연락처 관리 프로그램 (ver1.0)

HSRyuuu dev blog·2023년 3월 30일
0

연락처 관리 프로그램 GUI (ver1.0)

연락처를 파일로 관리하고, JTable을 이용해 출력한다.

이 프로그램은 대학교 2학년 JAVA 프로그래밍 강의에서 과제로 했던 주소록 관리 프로그램이다.

Java를 이 강의에서 처음 접했었고, 이 과제를 해결했을 당시에는 Java 언어도 잘 알지 못했고 GUI도 배운 지 2~3주 차 정도 되었을 때였기 때문에 데이터 효율, 가독성 등은 고려하지 않고 오직 구현에만 집중하였다. 전반적으로 실력이 부족했었던 것 같다.

이후에 기회가 된다면 다른 기능들을 추가해가며 업그레이드 해보려고 한다.


1. 전체 구성

아래와 같이 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();
	}
}

2. GUI 구성

  • 아래 코드의 panel1,2,3에 2-1, 2-2, 2-3을 끼워 넣으면 된다.
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);// 윈도우가 화면에 보임
	}

2-1. panel1

// 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 추가

2-2. panel2

//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);

2-3. panel3

//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);

3. 연락처 클래스

	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;
		}
	}

4. 연락처 출력 메서드 view_juso()

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 해주는 메소드
}

5. 연락처 추가 메서드

에러메시지 출력 방법

  1. msg1~msg6을 ""로 초기화 함.
  2. 각 항목에 문제가 있을경우 msg1~msg5 변수에 각 문자열을 대입
  3. msg6은 연락처의 요소를 각각 trim().isEmpty() 해서 하나라도 true가 반환되면 에러메시지 출력
  4. 만약 msg1~msg6중 하나라도 ""이 아니라면 어디선가 error가 발생했다는 의미 이므로 에러창 띄움

에러가 없다면 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();

}

6. 연락처 삭제 메서드

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("");

	}

7. 테이블을 갱신해 주는 메소드

=> 이 메소드가 실행되면 JFrame의 table이 갱신됨

	static void tableRefresh() {
		DefaultTableModel model = new DefaultTableModel(data,colNames);
		table.setModel(model);
	}

8. 연락처 정보를 갱신하는 메서드

출력하기 직전에 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();
	}

< Test >

데이터파일 ( juso.txt )

1) 처음 실행 시

2) 연락처 출력 버튼

3) 연락처 입력 => 연락처 등록 버튼

4) 삭제할 연락처 입력 => 연락처 삭제 버튼

5) 패턴에 안맞거나 빈칸이 있을 때

profile
Exciting dev life / 댓글, 피드백, 질문 환영합니다 !!!

0개의 댓글