Step17_JBDC (회원정보관리 Frame, PropertyChangeListener)
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);
}
}
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("수정 실패");
}
}
}
}
선생님과 다른 점이 두가지 있다.
첫번째는 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) {} //메소드 세부 내용은 생략
이 두가지 메소드를 추가하여 사용했다.
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);
}
}
}