java

Step17_JBDC (회원정보관리 Frame, PropertyChangeListener)

bono.html 2022. 8. 9. 13:15

 

 

TestFrame (참고 Frame)

 

package test.frame;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
/*
 *  //1. 선택된 row  인덱스를 읽어온다.
   int selectedIndex=table.getSelectedRow();
   
   //2. 선택된 row 의 첫번째(0번째) 칼럼의 숫자를 읽어온다 (삭제할 회원의 번호)
   int num=(int)model.getValueAt(selectedIndex, 0);
   
   
   -------------------------------------
   
   List<MemberDto>  list=dao.getList();
   
   for(MemberDto tmp:list){
      Object[] row={tmp.getNum(), tmp.getName(), tmp.getAddr()};
      model.addRow(row);
   }
 * 
 */
public class TestFrame extends JFrame{
   //필드
   JTextField inputName, inputAddr;
   DefaultTableModel model;
   JTable table;
   
   //생성자
   public TestFrame() {
      setLayout(new BorderLayout());
      
      JLabel label1=new JLabel("이름");
      inputName=new JTextField(10);
      
      JLabel label2=new JLabel("주소");
      inputAddr=new JTextField(10);
      
      JButton saveBtn=new JButton("저장");
      saveBtn.setActionCommand("save");
      
      //삭제 버튼 추가
      JButton deleteBtn=new JButton("삭제");
      deleteBtn.setActionCommand("delete");
      
      JPanel panel=new JPanel();
      panel.add(label1);
      panel.add(inputName);
      panel.add(label2);
      panel.add(inputAddr);
      panel.add(saveBtn);
      panel.add(deleteBtn);
      
      add(panel, BorderLayout.NORTH);
      
      //표형식으로 정보를 출력하기 위한 JTable
      table=new JTable();
      //칼럼명을 String[] 에 순서대로 준비
      String[] colNames= {"번호", "이름", "주소"};
      //테이블에 출력할 정보를 가지고 있는 모델 객체 (칼럼명, row 갯수)
      model=new DefaultTableModel(colNames, 0);
      //모델을 테이블에 연결한다.
      table.setModel(model);
      //스크롤이 가능 하도록 테이블을 JScrollPane 에 감싼다.
      JScrollPane scroll=new JScrollPane(table);
      //JScrollPane  을 프레임의 가운데에 배치하기 
      add(scroll, BorderLayout.CENTER);
      
      displayMember();
   }
   
   //테이블에 데이터 출력하는 메소드
   public void displayMember() {
      
      //model.setRowCount(0); //테이블에 출력된 데이터 reset 
      
      Object[] row1= {1, "김구라", "노량진"};
      model.addRow(row1);
      
      Object[] row2= {2, "해골", "행신동"};
      model.addRow(row2);
      
      Object[] row3= {3, "원숭이", "상도동"};
      model.addRow(row3);
      
   }
   
   
   //main  메소드
   public static void main(String[] args) {
      TestFrame f=new TestFrame();
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setBounds(100, 100, 800, 500);
      f.setVisible(true);
   }
}

TestFrame

 

 

MemberFrameMe (필자 작성 코드)

 

package test.frame;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

import test.dao.MemberDao;
import test.dto.MemberDto;
/*
 *  //1. 선택된 row  인덱스를 읽어온다.
   int selectedIndex=table.getSelectedRow();
   
   //2. 선택된 row 의 첫번째(0번째) 칼럼의 숫자를 읽어온다 (삭제할 회원의 번호)
   int num=(int)model.getValueAt(selectedIndex, 0);
   
   
   -------------------------------------
   
   List<MemberDto>  list=dao.getList();
   
   for(MemberDto tmp:list){
      Object[] row={tmp.getNum(), tmp.getName(), tmp.getAddr()};
      model.addRow(row);
   }
 * 
 */
public class MemberFrameMe extends JFrame implements ActionListener{
   //필드
   JTextField inputName, inputAddr;
   DefaultTableModel model;
   JTable table;
   
   //생성자
   public MemberFrameMe() {
      setLayout(new BorderLayout());
      
      JLabel label1=new JLabel("이름");
      inputName=new JTextField(10);
      
      JLabel label2=new JLabel("주소");
      inputAddr=new JTextField(10);
      
      JButton saveBtn=new JButton("저장");
      saveBtn.addActionListener(this);
      saveBtn.setActionCommand("save");
      
      //삭제 버튼 추가
      JButton deleteBtn=new JButton("삭제");
      deleteBtn.addActionListener(this);
      deleteBtn.setActionCommand("delete");
      
      JButton updateBtn=new JButton("수정");
      updateBtn.addActionListener(this);
      updateBtn.setActionCommand("update");
      
      JPanel panel=new JPanel();
      panel.add(label1);
      panel.add(inputName);
      panel.add(label2);
      panel.add(inputAddr);
      panel.add(saveBtn);
      panel.add(deleteBtn);
      panel.add(updateBtn);
      

      
      add(panel, BorderLayout.NORTH);
      
      //표형식으로 정보를 출력하기 위한 JTable
      table=new JTable();
      //칼럼명을 String[] 에 순서대로 준비
      String[] colNames= {"번호", "이름", "주소"};
      //테이블에 출력할 정보를 가지고 있는 모델 객체 (칼럼명, row 갯수)
      model=new DefaultTableModel(colNames, 0);
      //모델을 테이블에 연결한다.
      table.setModel(model);
      //스크롤이 가능 하도록 테이블을 JScrollPane 에 감싼다.
      JScrollPane scroll=new JScrollPane(table);
      //JScrollPane  을 프레임의 가운데에 배치하기 
      add(scroll, BorderLayout.CENTER);
      
      displayMember();
   }
   
   //테이블에 데이터 출력하는 메소드
   public void displayMember() {
      
      List<MemberDto> list=new MemberDao().getList();
      
      for(MemberDto tmp:list){
         Object[] row={tmp.getNum(), tmp.getName(), tmp.getAddr()};
         model.addRow(row);
      }
   }
   
   
   //main  메소드
   public static void main(String[] args) {
      MemberFrameMe f=new MemberFrameMe();
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setBounds(100, 100, 800, 500);
      f.setVisible(true);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      String command=e.getActionCommand();
      
      MemberDao dao=null;
      MemberDto dto=null;
      boolean isSuccess;
      //저장 버튼
      if(command.equals("save")) {
         dto=new MemberDto();
         dto.setName(inputName.getText());
         dto.setAddr(inputAddr.getText());
         dao=new MemberDao();
         isSuccess = dao.insert(dto);
          if(isSuccess) {
             System.out.println("회원정보를 저장 했습니다");
             model.setRowCount(0);
              displayMember();
          }else {
             System.out.println("저장 실패!");
          }
          
      }else if (command.equals("delete")) {
    	 dao=new MemberDao();
         int selectedIndex=table.getSelectedRow();
         int num=(int)model.getValueAt(selectedIndex, 0);
         isSuccess=dao.delete(num);
          if(isSuccess) {
             System.out.println("회원정보를 삭제 했습니다");
             model.setRowCount(0);
              displayMember();
          }else {
             System.out.println("삭제 실패!");
          }
      }else if (command.equals("update")) {
         dto=new MemberDto();
         int selectedIndex=table.getSelectedRow();
         int num=(int)model.getValueAt(selectedIndex, 0);
         dto.setNum(num);
         dto.setName(inputName.getText());
         dto.setAddr(inputAddr.getText());
          dao=new MemberDao();
          isSuccess=dao.update(dto);
          if(isSuccess) {
             System.out.println("회원정보를 수정 했습니다");
             model.setRowCount(0);
             displayMember();
          }else {
             System.out.println("수정 실패");
          }
      }
   }
}

MemberFrameMe

 

선생님과 다른 점이 두가지 있다.

 

첫번째는 model.setRowCount(0);를 displayMember(); 메소드 안에 포함시켜 코드 양을 줄였다. 필자처럼 if문마다 작성해도 되지만 선생님의 방식이 더 간편하다고 생각된다.

 

두번째는 delete 문 작성시 선택된 행을 배열타입으로 받아 사용했고 이를 활용해 선택한 행이 없을 경우 "선택된 row 가 없습니다."라는 dialog 창이 실행되는 기능을 추가한 것이다. 배열 타입으로 받았기 때문에 이후 dao를 활용할때 반복문을 사용한다.

 

필자 작성 코드 (delete 부분)

else if (command.equals("delete")) {
     dao=new MemberDao();
     int selectedIndex=table.getSelectedRow();
     int num=(int)model.getValueAt(selectedIndex, 0);
     isSuccess=dao.delete(num);
      if(isSuccess) {
         System.out.println("회원정보를 삭제 했습니다");
         model.setRowCount(0);
          displayMember();
      }else {
         System.out.println("삭제 실패!");
}

선생님 작성 코드 (delete 부분)

  else if(command.equals("delete")) {
     //선택된 row 인덱스를 int[] 로 얻어내기 
     int[] rows=table.getSelectedRows();
     //만일 어떤 row 도 선택하지 않았다면
     if(rows.length == 0) {
        JOptionPane.showMessageDialog(this, "선택된 row 가 없습니다.");
        //메소드를 여기서 끝낸다. 
        return;
     }

     //사용할 MemberDao 객체를 생성해서 
     MemberDao dao=new MemberDao();

     //반복문 돌면서 선택한 row 인덱스를 참조한다.
     for(int selectedRow:rows) {
        //선택한 row 의 가장 첫번째 칼럼에 있는 숫자 얻어내기
        int num=(int)model.getValueAt(selectedRow, 0);
        //MemberDao 객체를 이용해서 해당 번호의 회원 정보 삭제하기
        dao.delete(num);
     }         
     displayMember();
  }

 

 

MemberFrame (선생님 작성 코드, 수정 기능 리뉴얼)

 

MemberFrameMe 과 비교할때 위에서 언급했듯이 displayMember() 메소드 작성 방식 차이, delete 문의 기능 및 작성 방식 차이도 있다.

 

변경 사항이 가장 큰 부분은 update 부분이다.

기존에는 행을 선택하고 이름과 주소를 JTextField에 각각 입력 후 수정 버튼을 넣어 기능을 동작하였다.

현재코드는 원하는 셀을 더블클릭하고 수정한 후 셀을 벗어나면 바로 수정 기능이 동작한다.

 

이러한 기능은 PropertyChangeListener를 implements하여 사용하였으며

table.addPropertyChangeListener(this);

public void propertyChange(PropertyChangeEvent evt) {}  //메소드 세부 내용은 생략

이 두가지 메소드를 추가하여 사용했다.

 

MemberFrame

package test.frame;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

import test.dao.MemberDao;
import test.dto.MemberDto;
/*
 *  //1. 선택된 row  인덱스를 읽어온다.
   int selectedIndex=table.getSelectedRow();
   
   //2. 선택된 row 의 첫번째(0번째) 칼럼의 숫자를 읽어온다 (삭제할 회원의 번호)
   int num=(int)model.getValueAt(selectedIndex, 0);
   
   
   -------------------------------------
   
   List<MemberDto>  list=dao.getList();
   
   for(MemberDto tmp:list){
      Object[] row={tmp.getNum(), tmp.getName(), tmp.getAddr()};
      model.addRow(row);
   }
 * 
 */
public class MemberFrame extends JFrame 
                     implements ActionListener, PropertyChangeListener{
   //필드
   JTextField inputName, inputAddr;
   DefaultTableModel model;
   JTable table;
   
   
   //생성자
   public MemberFrame() {
      setLayout(new BorderLayout());
      
      JLabel label1=new JLabel("이름");
      inputName=new JTextField(10);
      
      JLabel label2=new JLabel("주소");
      inputAddr=new JTextField(10);
      
      JButton saveBtn=new JButton("저장");
      saveBtn.setActionCommand("save");
      
      //삭제 버튼 추가
      JButton deleteBtn=new JButton("삭제");
      deleteBtn.setActionCommand("delete");
      
      JPanel panel=new JPanel();
      panel.add(label1);
      panel.add(inputName);
      panel.add(label2);
      panel.add(inputAddr);
      panel.add(saveBtn);
      panel.add(deleteBtn);
      
      add(panel, BorderLayout.NORTH);
      
      //표형식으로 정보를 출력하기 위한 JTable
      table=new JTable();
      //칼럼명을 String[] 에 순서대로 준비
      String[] colNames= {"번호", "이름", "주소"};
      //테이블에 출력할 정보를 가지고 있는 모델 객체 (칼럼명, row 갯수)
      model=new DefaultTableModel(colNames, 0) {
         @Override
         public boolean isCellEditable(int row, int column) {
            
            if(column==0) { //만일 0 번째 칼럼이면
               //수정이 불가능 하도록 false 를 리턴해 준다.
               return false; 
            }else {
               //0 번째 칼럼 이외의 칼럼은 모두 수정 가능하도록 true 를 리턴해준다. 
               return true;
            }
         }
      };
      
      //모델을 테이블에 연결한다.
      table.setModel(model);
      //스크롤이 가능 하도록 테이블을 JScrollPane 에 감싼다.
      JScrollPane scroll=new JScrollPane(table);
      //JScrollPane  을 프레임의 가운데에 배치하기 
      add(scroll, BorderLayout.CENTER);
      
      //생성자에서 displayMember() 메소드를 호출해서 회원 목록을 한번 출력해 준다.
      displayMember();
      
      //버튼에 액션리스너 등록
      saveBtn.addActionListener(this);
      deleteBtn.addActionListener(this);
      
      //테이블에 값이 바뀌었는지 감시할 리스너 등록
      table.addPropertyChangeListener(this);
   }
   
   //테이블에 데이터 출력하는 메소드
   public void displayMember() {
      //이미 테이블에 출력된 내용 삭제
      model.setRowCount(0);
      
      //회원 전체 목록을 얻어와서
      List<MemberDto> list=new MemberDao().getList();
      
      for(MemberDto tmp:list) {
         //MemberDto 객체에 있는 내용을 Object[] 에 순서대로 담아서
         Object[] row= {tmp.getNum(), tmp.getName(), tmp.getAddr()};
         model.addRow(row);
      }
      
      
   }
   
   //main  메소드
   public static void main(String[] args) {
      MemberFrame f=new MemberFrame();
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      f.setBounds(100, 100, 800, 500);
      f.setVisible(true);
   }

   @Override
   public void actionPerformed(ActionEvent e) {
      //눌러진 버튼의 action command 값을 읽어와서 
      String command=e.getActionCommand();
      //분기한다. 
      if(command.equals("save")) {
         //1. 입력한 이름과, 주소를 읽어온다.
         String name=inputName.getText();
         String addr=inputAddr.getText();
         //2. 읽어온 이름과 주소를 MemberDto 객체를 생성해서 담는다.
         MemberDto dto=new MemberDto();
         dto.setName(name);
         dto.setAddr(addr);
         //3. MemberDao 객체를 이용해서 DB 에 저장을 한다. 
         MemberDao dao=new MemberDao();
         dao.insert(dto);
         //4. 목록이 다시 출력 되도록 한다.
         displayMember();
         
      }else if(command.equals("delete")) {
         //선택된 row 인덱스를 int[] 로 얻어내기 
         int[] rows=table.getSelectedRows();
         //만일 어떤 row 도 선택하지 않았다면
         if(rows.length == 0) {
            JOptionPane.showMessageDialog(this, "선택된 row 가 없습니다.");
            //메소드를 여기서 끝낸다. 
            return;
         }
         
         //사용할 MemberDao 객체를 생성해서 
         MemberDao dao=new MemberDao();
         
         //반복문 돌면서 선택한 row 인덱스를 참조한다.
         for(int selectedRow:rows) {
            //선택한 row 의 가장 첫번째 칼럼에 있는 숫자 얻어내기
            int num=(int)model.getValueAt(selectedRow, 0);
            //MemberDao 객체를 이용해서 해당 번호의 회원 정보 삭제하기
            dao.delete(num);
         }
         displayMember();
      }
   }
   
   @Override
   public void propertyChange(PropertyChangeEvent evt) {
      System.out.println("property change!");
      System.out.println("property name:"+evt.getPropertyName());
      System.out.println("isEditing:"+table.isEditing());
      
      //만일 property name 이 tableCellEditor 와 같고 table 이 수정 중이 아니라면
      if(evt.getPropertyName().equals("tableCellEditor") && !table.isEditing()) {
    	  //현재 선택된 row 의 정보를 읽어와서 수정 반영한다.
    	  int selectedRow=table.getSelectedRow();
    	  
    	  int num=(int)model.getValueAt(selectedRow, 0);
    	  String name=(String)model.getValueAt(selectedRow, 1);
    	  String addr=(String)model.getValueAt(selectedRow, 2);
    	  
    	  //MemberDto 객체에 담고
    	  MemberDto dto=new MemberDto(num, name, addr);
    	  //MemberDao 객체를 이용해서 수정반영한다.
    	  new MemberDao().update(dto);
      }
   }
}