Day29

2020. 11. 5. 09:32교육과정/KOSMO

키워드 : 비디오샵 완성본 / 싱글톤 패턴 / jfreechart

 

****

 

 

1. 비디오샵 - 대여관리 및 최종 완성

※ 대여관리 탭 구현 내용

 : 대여 내역 JTable에 자동 출력

 : 전화번호 입력 후 엔터 누르면 고객명 자동 출력

 : 대여 패널 내 비디오번호까지 입력 후 대여 버튼 클릭시 DB 추가 및 JTable 자동 업데이트

 : 반납 패널 내 비디오번호 입력 후 반납 버튼 클릭시 DB 추가 및 JTable 자동 업데이트

 

※ 비디오관리 탭 추가 구현 내용

 : 비디오정보 입력 패널 내 텍스트 변경 후 수정 버튼 클릭시 DB 반영, 비디오검색 내역 자동 업데이트, 입력창 초기화

 : 삭제 버튼 클릭시 선택된 비디오 정보 DB 삭제 반영, 비디오검색 내역 자동 업데이트, 입력창 초기화

 

※ 고객관리 탭 추가 구현 내용

 : 고객정보 입력 창 상단으로 이동

 : 검색 버튼 클릭시 고객정보 출력과 함께 검색창 초기화

 

◆ 오라클 DB 생성용 SQL ◆

더보기
-- 회원관리 테이블 생성
CREATE TABLE member (
    tel     varchar2(13),
    name    varchar2(20) NOT NULL,
    sub_tel varchar2(13),
    addr    varchar2(100),
    email   varchar2(20),
    CONSTRAINT pk_member_tel PRIMARY KEY (tel)
);
-- 비디오관리 테이블 생성
CREATE SEQUENCE video_num;
CREATE TABLE video (
    vnum    number(5),
    title   varchar2(40) NOT NULL,
    genre   varchar2(20) NOT NULL,
    dir     varchar2(30) NOT NULL,
    act     varchar2(20) NOT NULL,
    sul     varchar2(1000) NOT NULL,
    cnt     number(2),
    CONSTRAINT pk_video_vnum PRIMARY KEY (vnum)
);
-- 대여관리 테이블 생성
CREATE SEQUENCE rent_num;
CREATE TABLE rent (
    rnum    number,
    vnum    number,
    tel     varchar2(13),
    rent_date date,
    return_date date,
    CONSTRAINT pk_rent_rnum PRIMARY KEY (rnum),
    CONSTRAINT fk_rent_tel FOREIGN KEY (tel) REFERENCES member(tel),
    CONSTRAINT fk_rent_vnum FOREIGN KEY (vnum) REFERENCES video(vnum)
);

commit;
SELECT * FROM member;
SELECT * FROM video;
SELECT * FROM rent;
DESC member;
DESC video;
DESC rent;

 

 

 

◆ 비디오샵 메인 소스코드 ◆

<VideoShop 클래스>

더보기
package videoshop;

import java.awt.*;

import javax.swing.*;

import videoshop.view.CustomerView;
import videoshop.view.RentView;
import videoshop.view.VideoView;

public class VideoShop extends JFrame 
{
	CustomerView	customer;
	VideoView		video;
	RentView		rent;

	public VideoShop(){
		
			customer = new CustomerView();
			video	 = new VideoView();
			rent	 = new RentView();

			JTabbedPane  pane = new JTabbedPane();
			pane.addTab("고객관리", customer );
			pane.addTab("비디오관리", video);
			pane.addTab("대여관리", rent );

			pane.setSelectedIndex(2);

			getContentPane().add("Center", pane );
			pack();
			setVisible( true );

			setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );	
	}
	public static void main(String[] args) 
	{
			new VideoShop();
	}
}

<DBcon 클래스>

더보기
package videoshop.model;

import java.sql.Connection;
import java.sql.DriverManager;

public class DBcon {

	static Connection con;
	String url = "jdbc:oracle:thin:@192.168.0.17:1521:orcl";
	String user = "scott";
	String pass = "tiger";
	
	private DBcon() throws Exception {
		// 1. 드라이버로딩
		// 2. Connection 연결객체 얻어오기
		Class.forName("oracle.jdbc.driver.OracleDriver");
		con = DriverManager.getConnection(url,user, pass);	
	} // end of 생성자함수
	
	public static Connection getInstance() throws Exception {
		if (con == null) new DBcon();
		return con;
	}
	
}

 

◆ 고객관리 탭 소스코드 ◆

<CustomerVO 클래스>

더보기
package videoshop.model.vo;

public class CustomerVO {
	
	String custTel;
	String custName;
	String custSubTel;
	String custAddr;
	String custmail;
	
	// constructor
	public CustomerVO() {
		super();
	}
	
	// setter, getter
	public String getCustTel() {
		return custTel;
	}
	public void setCustTel(String custTel) {
		this.custTel = custTel;
	}
	public String getCustName() {
		return custName;
	}
	public void setCustName(String custName) {
		this.custName = custName;
	}
	public String getCustSubTel() {
		return custSubTel;
	}
	public void setCustSubTel(String custSubTel) {
		this.custSubTel = custSubTel;
	}
	public String getCustAddr() {
		return custAddr;
	}
	public void setCustAddr(String custAddr) {
		this.custAddr = custAddr;
	}
	public String getCustmail() {
		return custmail;
	}
	public void setCustmail(String custmail) {
		this.custmail = custmail;
	}
	
}

<CustomerView 클래스>

더보기
package	 videoshop.view;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import videoshop.model.CustomerDAO;
import videoshop.model.vo.CustomerVO;



public class CustomerView extends JPanel implements ActionListener
{
	JFrame		frm;
	JTextField	tfCustName, tfCustTel,  tfCustTelAid, tfCustAddr, tfCustEmail;
	JButton		bCustRegist, bCustModify;
	
	JTextField  tfCustNameSearch,  tfCustTelSearch;
	JButton		bCustNameSearch,  bCustTelSearch;

	// 모델단 - 비지니스 로직
	CustomerDAO dao;
	
	// 회원번호가 있을 경우에만
	// int memberId;
	
	/** constructor method **/
	public CustomerView(){
		addLayout();
		eventProc();
		
		try {
			dao = new CustomerDAO();
			System.out.println("DB 연결성공");
		} catch (Exception e) {
			System.out.println("DB 연결실패:" + e.toString());
			e.printStackTrace();
		}
	} // end of 생성자함수
	
	/** 버튼 이벤트와 객체 연결 **/
	public void eventProc() {
		bCustRegist.addActionListener(this);
		bCustModify.addActionListener(this);
		bCustNameSearch.addActionListener(this);
		bCustTelSearch.addActionListener(this);
	} // end of eventproc
	
	/** 버튼 이벤트 핸들러 **/
	public void actionPerformed(ActionEvent ev) {
		Object evt = ev.getSource();
		if (evt == bCustRegist) {
			insertCustomer();					// 회원가입 버튼이 눌렸을 때
			clearTextFields();
		}else if (evt == bCustModify) {
			modifyCustomer();					// 회원수정 버튼이 눌렸을 때
			clearTextFields();
		}else if (evt == bCustTelSearch) {
			searchByTel();						// 전화번호로 검색 버튼이 눌렸을 때
			tfCustTelSearch.setText(null);		// 전화번호 검색창 초기화
		}else if (evt == bCustNameSearch) {
			searchByName();						// 이름으로 검색 버튼이 눌렸을 때
			tfCustNameSearch.setText(null);		// 이름 검색창 초기화
		}
	} // end of 버튼 이벤트 핸들러
	
	
	/**
	 * 함수명 : clearTextFields()
	 * 인자 : 없음
	 * 리턴값 : 없음
	 * 역할 : 입력창 클리어
	 */
	void clearTextFields() {
		tfCustName	.setText(null);
		tfCustTel	.setText(null);
		tfCustAddr	.setText(null);
		tfCustEmail .setText(null);
		tfCustTelAid.setText(null);
		tfCustNameSearch.setText(null);
		tfCustTelSearch.setText(null);
	} // end of clearTextFields
	
	
	/**
	 * 함수명 : insertCustomer()
	 * 인자 : 없음
	 * 리턴값 : void
	 * 역할 : 회원가입을 위해 사용자 입력값을 받아서 모델로 전달
	 */
	void insertCustomer() {
		// 1. 화면 입력값 얻어오기
		// 2. VO 객체의 멤버 변수로 화면의 입려값들을 저장
		// 3. 모델단의 regist() 호출
		CustomerVO vo = new CustomerVO();			// 1.
		vo.setCustName(tfCustName.getText());		// 2.
		vo.setCustTel(tfCustTel.getText());
		vo.setCustAddr(tfCustAddr.getText());
		vo.setCustmail(tfCustEmail.getText());
		vo.setCustSubTel(tfCustTelAid.getText());
		
		try {
			dao.regist(vo);							// 3. 회원가입 메소드
		}catch (Exception e) {
			System.out.println("입력 실패: " + e.toString());
		}
	} // end of insertCustomer
	

	/**
	 * 함수명 : modifyCustomer()
	 * 인자 : 없음
	 * 리턴값 : void
	 * 역할 : 수정버튼 눌렸을 때 Tel을 제외한 DB의 회원정보를 수정
	 */
	void modifyCustomer() {
		CustomerVO vo = new CustomerVO();
		vo.setCustTel	(tfCustTel	 .getText());
		vo.setCustName	(tfCustName  .getText());
		vo.setCustAddr	(tfCustAddr  .getText());
		vo.setCustSubTel(tfCustTelAid.getText());
		vo.setCustmail	(tfCustEmail .getText());
		try {
			dao.modify(vo);
		}catch (Exception e) {
			System.out.println("수정실패: " + e.toString());
		}
	} // end of modifyCustomer

	
	/**
	 * 함수명 : searchByTel()
	 * 인자 : 없음
	 * 리턴값 : void
	 * 역할 : 전화번호로 검색시 고객 정보 불러와서 화면에 출력
	 */
	void searchByTel() {
		String tel = tfCustTelSearch.getText();
		try {
			CustomerVO vo = dao.searchTel(tel);
//			memberId = be.getCustNo();				
			tfCustName	.setText(vo.getCustName());
			tfCustTel	.setText(vo.getCustTel());
			tfCustTelAid.setText(vo.getCustSubTel());
			tfCustAddr	.setText(vo.getCustAddr());
			tfCustEmail	.setText(vo.getCustmail());
		} catch (Exception e) {
			System.out.println("전화번호 검색 실패: " + e.toString());
			e.printStackTrace();
		}
	} // end of searchByTel
	
	
	/**
	 * 함수명 : searchByName
	 * 인자 : 없음
	 * 리턴값 : void
	 * 역할 : 이름검색 버튼을 눌렀을 때 TextField의 값과 일치하는 회원정보를 출력
	 */
	void searchByName() {
		String name = tfCustNameSearch.getText();
		try {
			ArrayList list = dao.searchName(name);
			for (int i=0; i<list.size(); i++) {
				CustomerVO vo = (CustomerVO)list.get(i);
				tfCustName	.setText(vo.getCustName());
				tfCustTel	.setText(vo.getCustTel());
				tfCustTelAid.setText(vo.getCustSubTel());
				tfCustAddr	.setText(vo.getCustAddr());
				tfCustEmail	.setText(vo.getCustmail());
			}
		} catch (Exception e) {
			System.out.println("검색실패:" + e.toString());
		}
	} // end of searchByName

	
	/** 화면구성 **/
	public void addLayout()
	{
		
			tfCustName			= new JTextField(20);
			tfCustTel			= new JTextField(20);
			tfCustTelAid		= new JTextField(20);
			tfCustAddr			= new JTextField(20);
			tfCustEmail			= new JTextField(20);


			tfCustNameSearch	= new JTextField(20);
			tfCustTelSearch		= new JTextField(20);

			bCustRegist			= new JButton("회원가입");
			bCustModify			= new JButton("회원수정");
			bCustNameSearch		= new JButton("이름검색");
			bCustTelSearch		= new JButton("번호검색");

			// 회원가입 부분 붙이기 
			//		( 그 복잡하다던 GridBagLayout을 사용해서 복잡해 보임..다른 쉬운것으로...대치 가능 )
			JPanel			pRegist		= new JPanel();
			pRegist.setLayout( new GridBagLayout() );
				GridBagConstraints	cbc = new GridBagConstraints();
				cbc.weightx	= 1.0;
				cbc.weighty	 = 1.0;
				cbc.fill				= GridBagConstraints.BOTH;
			cbc.gridx	=	0;	 			cbc.gridy	=  0;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( new JLabel("	이	름	") ,	cbc );
			cbc.gridx	=	1;	 			cbc.gridy	=  0;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( tfCustName ,	cbc );
			cbc.gridx	=	2;	 			cbc.gridy	=  0;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( bCustModify,	cbc );
			cbc.gridx	=	3;	 			cbc.gridy	=  0;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( bCustRegist,	cbc );

			cbc.gridx	=	0;	 			cbc.gridy	=  1;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( new JLabel("	전	화	") ,	cbc );
			cbc.gridx	=	1;	 			cbc.gridy	=  1;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add(  tfCustTel ,	cbc );
			cbc.gridx	=	2;	 			cbc.gridy	=  1;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( new JLabel(" 추가전화  ") ,	cbc );
			cbc.gridx	=	3;	 			cbc.gridy	=  1;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( tfCustTelAid ,	cbc );

			cbc.gridx	=	0;	 			cbc.gridy	=  2;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( new JLabel("	주	소	") ,	cbc );
			cbc.gridx	=	1;	 			cbc.gridy	=  2;			cbc.gridwidth	=	3;			cbc.gridheight= 1;
			pRegist.add(  tfCustAddr  ,	cbc );

			cbc.gridx	=	0;	 			cbc.gridy	=  3;			cbc.gridwidth	=	1;			cbc.gridheight= 1;
			pRegist.add( new JLabel("	이메일	") ,	cbc );
			cbc.gridx	=	1;	 			cbc.gridy	=  3;			cbc.gridwidth	=	3;			cbc.gridheight= 1;
			pRegist.add( tfCustEmail ,	cbc );




			// 회원검색 부분 붙이기
			JPanel			pSearch		= new JPanel();
			pSearch.setLayout( new GridLayout(2, 1) );
					JPanel	pSearchName	= new JPanel();
					pSearchName.add(	new JLabel("		이 	름	"));
					pSearchName.add(	tfCustNameSearch );
					pSearchName.add(	bCustNameSearch );
					JPanel	pSearchTel	= new JPanel();
					pSearchTel.add(		new JLabel("	전화번호	"));
					pSearchTel.add(	tfCustTelSearch );
					pSearchTel.add(	bCustTelSearch );
			pSearch.add(	 pSearchName );
			pSearch.add( pSearchTel );

			// 전체 패널에 붙이기
			setLayout( new BorderLayout() );
//			add("Center",		pRegist );
			add("North",		pRegist );
			add("South",		pSearch );
			
	} // end of addLayout

} // end of CustomerView 클래스
				 	

<CustomerDAO 클래스>

더보기
package	  videoshop.model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;

import javax.swing.JOptionPane;

import videoshop.model.vo.CustomerVO;


public class  CustomerDAO {

		Connection	con;

		/** constructor method **/
		public	CustomerDAO() throws Exception{
			con = DBcon.getInstance();
		} // end of 생성자함수

		/** 회원가입 **/
		public  void		regist( CustomerVO cust )  throws Exception {
		/*
			1.  sql 작성하기		( insert 문 작성 : CustomerVO의 멤버변수로 각각 지정)
			2.  sql 전송객체 얻어오기( PreparedStatement가 더 적합할 듯 )
			3.  sql 전송			( 전송전에 ?로 지정 )
			4.  닫기				( Connection은 닫으면 안됨 )
		*/
			PreparedStatement ps=null;							// 2-1.
			
			try {
				String sql = "INSERT INTO member "				// 1.
					+ "(tel, name, sub_tel, addr, email) "
					+ "VALUES (?, ?, ?, ?, ?)";
				
				ps = con.prepareStatement(sql);					// 2-2.
				ps.setString(1, cust.getCustTel());
				ps.setString(2, cust.getCustName());
				ps.setString(3, cust.getCustSubTel());
				ps.setString(4, cust.getCustAddr());
				ps.setString(5, cust.getCustmail());
				
				int result = ps.executeUpdate();				// 3.
				System.out.println(result+"행을 입력");
				
			}finally {
				try { ps.close(); } catch(Exception e) {}		// 4
			}
		} // end of regist

		
		/** 회원정보 수정 **/
		public	void		modify( CustomerVO cust) throws Exception{
		/*
			1.  sql 작성하기		( update 문 작성 : CustomerVO의 멤버변수로 각각 지정)
			2.  sql 전송객체 얻어오기( PreparedStatement가 더 적합할 듯 )
			3.  sql 전송			( 전송전에 ?로 지정 )
			4.  닫기				( Connection은 닫으면 안됨 )
		*/
			PreparedStatement ps=null;							// 2-1.
			
			try {
				String sql = "UPDATE member SET "				// 1.
					+ "name=?, sub_tel=?, addr=?, email=? "
					+ "WHERE tel=?";
				ps = con.prepareStatement(sql);					// 2-2.
				ps.setString(1, cust.getCustName());
				ps.setString(2, cust.getCustSubTel());
				ps.setString(3, cust.getCustAddr());
				ps.setString(4, cust.getCustmail());
				ps.setString(5, cust.getCustTel());
				
				int result = ps.executeUpdate();				// 3.
				System.out.println(result+"행을 입력");
			}finally {
				try { ps.close(); } catch(Exception e) {}		// 4.
			}
		} // end of modify

		/** 이름 검색 **/
		public  ArrayList	searchName(	String name ) throws Exception {
		/*
			1.  sql 작성하기	 	( select 문
			 					   : 함수의 인자로 넘어온 이름과 같은 조건의 레코드 검색 )
			2.  sql 전송객체 얻어오기( Statement / PreparedStatement 모두 적합 )
			3.  sql 전송		 	( ResultSet 의 데이타를 얻어서 멤버 필드에 지정 )
			4.  닫기			 	( Connection은 닫으면 안됨 )

			#   생각해 보기
				- 동명 이인이 여러명 인 경우는 어떻게 처리할까?
		*/
				ArrayList  list = new ArrayList();
				PreparedStatement ps = null;					// 2-1.
				try {
					String sql =								// 1.
						"SELECT * FROM member WHERE name = ?";
					
					ps = con.prepareStatement(sql);				// 2-2.
					ps.setString(1, name);
					
					ResultSet rs = ps.executeQuery();			// 3.
					System.out.println(rs);
					
						if (rs.next()) {
							CustomerVO vo = new CustomerVO();
							vo.setCustName	(rs.getString("NAME"));
							vo.setCustTel	(rs.getString("TEL"));
							vo.setCustSubTel(rs.getString("SUB_TEL"));
							vo.setCustAddr	(rs.getString("ADDR"));
							vo.setCustmail	(rs.getString("EMAIL"));
							list.add(vo);
						}

				} finally {
					try { ps.close(); } catch(Exception e) {}	// 4.
				}
	
				return list;
		} // end of searchName

		/** 전화번호 검색 **/
		public CustomerVO     searchTel( String  tel ) throws Exception {
		/*
			1.  sql 작성하기	 	( select 문
			 					   : 함수의 인자로 넘어온 전화번호과 같은 조건의 레코드 검색 )
			2.  sql 전송객체 얻어오기( Statement / PreparedStatement 모두 적합 )
			3.  sql 전송			( ResultSet 의 데이타를 얻어서 멤버 필드에 지정 )
								   결과집합의 컬럼값을 CustomerVO의 각각 멤버 지정
			4.  닫기			 	( Connection은 닫으면 안됨 )
		*/
				CustomerVO vo = new CustomerVO();
				PreparedStatement ps = null;					// 2-1.
				
				try {
					String sql =								// 1. 
						"SELECT * FROM member WHERE tel = ?";
					ps = con.prepareStatement(sql);				// 2-2.
					ps.setString(1,  tel);
					
					ResultSet rs = ps.executeQuery();			// 3.
					if (rs.next()) {
						vo.setCustName(rs.getString("NAME"));
						vo.setCustTel(rs.getString("TEL"));
						vo.setCustSubTel(rs.getString("SUB_TEL"));
						vo.setCustAddr(rs.getString("ADDR"));
						vo.setCustmail(rs.getString("EMAIL"));
					}
				}finally {
					try { ps.close(); } catch(Exception e) {}	// 4.
				}
				return vo;
		} // end of searchTel
		
} // end of CustomerDAO

 

◆ 비디오관리 탭 소스코드 ◆

<VideoVO 클래스>

더보기
package videoshop.model.vo;

public class VideoVO {
	// 멤버변수 - Video 테이블의 컬럼과 매칭하도록 선언
	int vnum;
	String title;
	String genre;
	String dir;
	String act;
	String sul;
	int count;
	
	// 생성자 함수
	public VideoVO() {
		
	}
	// setter, getter
	public int getVnum() {
		return vnum;
	}
	public void setVnum(int vnum) {
		this.vnum = vnum;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getGenre() {
		return genre;
	}
	public void setGenre(String genre) {
		this.genre = genre;
	}
	public String getDir() {
		return dir;
	}
	public void setDir(String dir) {
		this.dir = dir;
	}
	public String getAct() {
		return act;
	}
	public void setAct(String act) {
		this.act = act;
	}
	public String getSul() {
		return sul;
	}
	public void setSul(String sul) {
		this.sul = sul;
	}
	public int getCount() {
		return count;
	}
	public void setCount(int count) {
		this.count = count;
	}
	
	
}

<VideoView 클래스>

더보기
package	 videoshop.view;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.table.AbstractTableModel;

import videoshop.model.VideoDAO;
import videoshop.model.vo.VideoVO;


public class VideoView extends JPanel 
{	
	//	member field
	JTextField	tfVideoNum, tfVideoTitle, tfVideoDirector, tfVideoActor;
	JComboBox	comVideoGenre;
	JTextArea	taVideoContent;

	JCheckBox	cbMultiInsert;
	JTextField	tfInsertCount;

	JButton		bVideoInsert, bVideoModify, bVideoDelete;

	JComboBox	comVideoSearch;
	JTextField	tfVideoSearch;
	JTable		tableVideo;
	
	VideoTableModel tbModelVideo;
	VideoDAO dao;
	

	//##############################################
	//	constructor method
	public VideoView(){
		addLayout(); 	// 화면설계
		initStyle();
		eventProc();
		connectDB();	// DB연결
	} // end of 생성자함수
	
	/** DB연결 **/
	public void connectDB() {
		try {
			dao = new VideoDAO();
			System.out.println("DB 연결성공 - 비디오관리");
		} catch (Exception e) {
			System.out.println("DB 연결실패 - 비디오관리");
		}
	} // end of connectDB
	
	/** 버튼 이벤트와 객체 연결 **/
	public void eventProc(){
		ButtonEventHandler hdlr = new ButtonEventHandler();
		bVideoInsert.addActionListener(hdlr);
		bVideoModify.addActionListener(hdlr);
		bVideoDelete.addActionListener(hdlr);
		tfVideoSearch.addActionListener(hdlr);
		
		/** 다중입고 체크박스 이벤트 **/
		cbMultiInsert.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				boolean flag = cbMultiInsert.isSelected();
				tfInsertCount.setEditable(flag);
			}
		}); // end of 다중입고 체크박스 이벤트
		
		/** 검색된 데이터 클릭했을 때 좌측에 비디오정보 출력하기 **/ 
		tableVideo.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				int col = 0;					// 비디오번호는 0번째 컬럼이라 고정
				int row = tableVideo.getSelectedRow();
				int vNum = (Integer)tableVideo.getValueAt(row, col);

				try {
					VideoVO vo = dao.searchByPK(vNum);
					tfVideoTitle.setText(vo.getTitle());
					tfVideoDirector.setText(vo.getDir());
					tfVideoActor.setText(vo.getAct());
					taVideoContent.setText(vo.getSul());
					comVideoGenre.setSelectedItem(vo.getGenre());
					tfVideoNum.setText(Integer.toString(vo.getVnum()));
				} catch (Exception e1) {
					System.out.println("검색 실패:" + e.toString());
					e1.printStackTrace();
				}
			}
		}); // end of 비디오정보 출력하기
		
	} // end of eventproc
	
	/** 버튼 이벤트 핸들러를 만들기 위한 이너클래스 **/
	class ButtonEventHandler implements ActionListener{
		public void actionPerformed(ActionEvent ev){
			Object o = ev.getSource();
			
			if(o==bVideoInsert){  
				registVideo();					// 비디오 등록
				clearTextField();
			}
			else if(o==bVideoModify){  
				modifyVideo();					// 비디오 정보 수정
				clearTextField();
				searchVideo();
			}
			else if(o==bVideoDelete){  
				deleteVideo();					// 비디오 정보 삭제
				clearTextField();
				searchVideo();
			}
			else if(o==tfVideoSearch){
				searchVideo();					// 비디오 검색
			}
		}
	} // end of 버튼 이벤트 핸들러
	
	/** 입력창 초기화 **/
	public void clearTextField() {
		tfVideoNum		.setText(null);
		tfVideoTitle	.setText(null);
		tfVideoActor	.setText(null);
		tfVideoDirector .setText(null);
		taVideoContent.setText(null);
		tfInsertCount.setEditable(true);	
		tfInsertCount.setText("1");
		tfInsertCount.setEditable(false);	
	} // end of clearTextField
	
	/** 입고 클릭시  - 비디오 정보 등록 **/
	public void registVideo(){
		// 1. 화면에서 사용자 입력값 얻어오기
		// 2. VedioVO의 멤버변수로 1번값들을 지정
		// 3. 모델단(VedioDAO)의 insertVideo() 호출
		String genre = (String)comVideoGenre.getSelectedItem();
		String title = tfVideoTitle.getText();
		String actor = tfVideoActor.getText();
		String director = tfVideoDirector.getText();
		String content = taVideoContent.getText();
		int count = Integer.parseInt(tfInsertCount.getText());
		
		VideoVO vo = new VideoVO();
		vo.setGenre(genre);
		vo.setTitle(title);
		vo.setAct(actor);
		vo.setDir(director);
		vo.setSul(content);
		vo.setCount(count);
	
		try {
			dao.insertVideo(vo, count);
		} catch (Exception e) {
			System.out.println("입고실패:" + e.toString());
			e.printStackTrace();
		}
	} // end of registVideo
	
	/** 비디오번호, 다중입고 수량 입력 불가 처리 **/
	public void initStyle(){
		tfVideoNum.setEditable(false);
		tfInsertCount.setEditable(false);		
		tfInsertCount.setHorizontalAlignment(JTextField.RIGHT);
	} // end of iniStyle

	
	/** 수정 클릭시 - 비디오 정보 수정 **/
	public void modifyVideo(){
		VideoVO vo = new VideoVO();
		vo.setGenre((String)comVideoGenre.getSelectedItem());
		vo.setTitle(tfVideoTitle.getText());
		vo.setDir(tfVideoDirector.getText());
		vo.setAct(tfVideoActor.getText());
		vo.setSul(taVideoContent.getText());
		vo.setVnum(Integer.parseInt(tfVideoNum.getText()));
		try {
			dao.modify(vo);
		}catch (Exception e) {
			System.out.println("수정실패:" + e.toString());
		}
	} // end of modifyVideo
	
	/** 삭제 클릭시 - 비디오 정보 삭제 **/
	public void deleteVideo(){
		
		String vnum = tfVideoNum.getText();
		try {
			dao.delete(vnum);
		} catch (Exception e) {
			System.out.println("삭제실패:" + e.toString());
		}
	} // end of deleteVideo
	
	/** 비디오현황검색 **/
	public void searchVideo(){
		int idx = comVideoSearch.getSelectedIndex();
		String word = tfVideoSearch.getText();
		try {
			ArrayList data = dao.searchVideo(idx, word);
			tbModelVideo.data = data;
			tableVideo.setModel(tbModelVideo);
			tbModelVideo.fireTableDataChanged();
		} catch (Exception e) {
			System.out.println("검색실패:" + e.toString());
			e.printStackTrace();
		}
	} // end of searchVideo


	/**  화면설계 메소드 **/
	public void addLayout(){
		//멤버변수의 객체 생성
		tfVideoNum = new JTextField();
		tfVideoTitle = new JTextField();
		tfVideoDirector = new JTextField();
		tfVideoActor = new JTextField();
		
		String []cbJanreStr = {"멜로","엑션","스릴","코미디"};
		comVideoGenre = new JComboBox(cbJanreStr);
		taVideoContent = new JTextArea();
		
		cbMultiInsert = new JCheckBox("다중입고");
		tfInsertCount = new JTextField("1",5);
	
		bVideoInsert = new JButton("입고");
		bVideoModify = new JButton("수정");
		bVideoDelete = new JButton("삭제");
		
		String []cbVideoSearch = {"제목","감독"};
		comVideoSearch = new JComboBox(cbVideoSearch);
		tfVideoSearch = new JTextField(15);
		
		tbModelVideo = new VideoTableModel();
		tableVideo = new JTable(tbModelVideo);

		//*********************************************************************
		// 화면 구성
		setLayout(new GridLayout(1,2));
		// 왼쪽 영역
		JPanel pLeft = new JPanel();
		pLeft.setBorder(new TitledBorder("비디오정보 입력"));
		pLeft.setLayout(new BorderLayout());
			// 왼쪽 중앙 영역
			JPanel pLeftCenter = new JPanel();
			pLeftCenter.setLayout(new BorderLayout());
				JPanel pLeftCenterNorth = new JPanel();
				pLeftCenterNorth.setLayout(new GridLayout(5,2));
				pLeftCenterNorth.add(new JLabel("비디오번호"));
				pLeftCenterNorth.add(tfVideoNum);
				pLeftCenterNorth.add(new JLabel("장르"));
				pLeftCenterNorth.add(comVideoGenre);
				pLeftCenterNorth.add(new JLabel("제목"));
				pLeftCenterNorth.add(tfVideoTitle);
				pLeftCenterNorth.add(new JLabel("감독"));
				pLeftCenterNorth.add(tfVideoDirector);
				pLeftCenterNorth.add(new JLabel("배우"));
				pLeftCenterNorth.add(tfVideoActor);
				
				JPanel pLeftCenterCenter = new JPanel();
				pLeftCenterCenter.setLayout(new BorderLayout());
				pLeftCenterCenter.add(new JLabel("설명"),BorderLayout.WEST);
				pLeftCenterCenter.add(taVideoContent, BorderLayout.CENTER);
				
						
				pLeftCenter.add(pLeftCenterNorth, BorderLayout.NORTH);
				pLeftCenter.add(pLeftCenterCenter, BorderLayout.CENTER);
			
			// 왼쪽 아래 영역
			JPanel pLeftSouth = new JPanel();
			pLeftSouth.setLayout(new GridLayout(2,1));
				JPanel pLeftSouth1 = new JPanel();
					pLeftSouth1.setBorder(new TitledBorder("다중입력시 선택하세요"));
					pLeftSouth1.add(cbMultiInsert);
					pLeftSouth1.add(tfInsertCount);
					pLeftSouth1.add(new JLabel("개"));
				
				JPanel pLeftSouth2 = new JPanel();
					pLeftSouth2.setLayout(new GridLayout(1,3));
					pLeftSouth2.add(bVideoInsert);
					pLeftSouth2.add(bVideoModify);
					pLeftSouth2.add(bVideoDelete);
				
				pLeftSouth.add(pLeftSouth1);
				pLeftSouth.add(pLeftSouth2);
			
		
		pLeft.add(pLeftCenter, BorderLayout.CENTER);
		pLeft.add(pLeftSouth, BorderLayout.SOUTH);
		
		// 오른쪽 영역
		JPanel pRight = new JPanel();
		pRight.setBorder(new TitledBorder("비디오검색"));
		pRight.setLayout(new BorderLayout());
			JPanel pRightNorth = new JPanel();
			pRightNorth.add(comVideoSearch);
			pRightNorth.add(tfVideoSearch);
		pRight.add(pRightNorth, BorderLayout.NORTH);
		pRight.add(new JScrollPane(tableVideo), BorderLayout.CENTER);
		
		add(pLeft);
		add(pRight);
		
	} // end of addLayout
	
	
	/** JTable 관리를 위한 TableModel 이너클래스 **/ 
	class VideoTableModel extends AbstractTableModel { 
		  
		ArrayList data = new ArrayList();
		String [] columnNames = {"비디오번호","제목","감독","배우"};

		    public int getColumnCount() { 
		        return columnNames.length; 
		    } 
		    public int getRowCount() { 
		        return data.size(); 
		    } 
		    public Object getValueAt(int row, int col) { 
				ArrayList temp = (ArrayList)data.get( row );
		        return temp.get( col ); 
		    }
		    public String getColumnName(int col){
		    	return columnNames[col];
		    }
	} // end of VideoTableModel
	
} // end of VideoView 클래스


<VideoDAO 클래스>

더보기
package videoshop.model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;

import videoshop.model.vo.VideoVO;

public class VideoDAO{
	
	Connection con;
	
	/** constructor method **/
	public VideoDAO() throws Exception{
		con = DBcon.getInstance();
	} // end of 생성자 함수
	
	/** 입고 : VideoView의 registVideo()에서 작동할 메소드 **/
	public void insertVideo(VideoVO vo, int count) throws Exception {
		
		PreparedStatement ps = null;
		try {
		// 3. sql 문장 만들기
		String sql = "INSERT INTO video "
				+ "(vnum, title, genre, dir, act, sul, cnt) "
				+ "VALUES (video_num.NEXTVAL, ?,?,?,?,?,?)";
		// 4. sql 전송객체 (PreparedStatement)		
		ps = con.prepareStatement(sql);
		ps.setString(1, vo.getTitle());
		ps.setString(2, vo.getGenre());
		ps.setString(3, vo.getDir());
		ps.setString(4, vo.getAct());
		ps.setString(5, vo.getSul());
		ps.setInt	(6, vo.getCount());
		// 5. sql 전송
		int result = 0;;
		for (int i=0; i<count; i++) {
			result = ps.executeUpdate();
		}
		System.out.println(result+"행을 입력");
		} finally {
		// 6. 닫기 ( 연결객체 닫지 않음 )
		try { ps.close(); } catch(Exception e) {}
		}
	} // end of insertVideo
	
	
	/** 수정 : VideoView의 modifyVideo()에서 작동할 메소드 **/
	public void modify(VideoVO vo) throws Exception {
		PreparedStatement ps = null;
		try {
			String sql = "UPDATE video SET genre=?, title=?, dir=?, "
					+ "act=?, sul=? WHERE vnum=?";
			ps = con.prepareStatement(sql);
			ps.setString(1, vo.getGenre());
			ps.setString(2, vo.getTitle());
			ps.setString(3, vo.getDir());
			ps.setString(4, vo.getAct());
			ps.setString(5, vo.getSul());
			ps.setInt(6, vo.getVnum());
			System.out.println(sql);
			int result = ps.executeUpdate();
			System.out.println(result+"행을 입력");
		} finally {
			try { ps.close(); } catch(Exception e) {}
		}
	} // end of modify
	
	/** 삭제 : VideoView의 deleteVideo()에서 작동할 메소드 **/
	public void delete(String vnum) throws Exception {
		Statement st = null;
		try {
			String sql = "DELETE FROM video WHERE vnum=" + vnum + "";
			st = con.createStatement();
			System.out.println(sql);
			int result = st.executeUpdate(sql);
			System.out.println(result+"행을 입력");
		} finally {
			try { st.close(); } catch(Exception e) {}
		}
	} // end of delete
	
	
	/** 비디오검색 : VideoView의 searchVideo()에서 작동할 메소드 **/
	public ArrayList searchVideo(int idx, String word) throws Exception {
		String[] colName = {"title", "dir"};
		String sql = "SELECT vnum, title, dir, act FROM video WHERE "
						+ colName[idx] + " LIKE '%" + word + "%'";	
		// sql문 내에 자바의 변수를 사용할 경우에는 자동 '' 문제로 ps를 사용할 수 없다. 
		System.out.println(sql);
		
		Statement st = con.createStatement();
		ResultSet rs = st.executeQuery(sql);
		ArrayList data = new ArrayList();
		while (rs.next()) {
			ArrayList temp = new ArrayList();
			temp.add(rs.getInt("vnum"));
			temp.add(rs.getString("title"));
			temp.add(rs.getString("dir"));
			temp.add(rs.getString("act"));
			data.add(temp);
		}
		rs.close();
		st.close();
		return data;
	} // end of searchVideo
	
	/** 검색된 데이터를 클릭했을 때 좌측에 비디오정보 출력하기**/
	public VideoVO searchByPK(int vNum) throws Exception {
		VideoVO vo = new VideoVO();
		PreparedStatement ps = null;
		try {
			String sql = "SELECT * FROM video WHERE vnum = ?";
			ps = con.prepareStatement(sql);
			ps.setInt(1, vNum);
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				vo.setTitle	(rs.getString("TITLE"));
				vo.setDir	(rs.getString("DIR"));
				vo.setAct(rs.getString("ACT"));
				vo.setSul(rs.getString("SUL"));
				vo.setGenre(rs.getString("GENRE"));
				vo.setVnum(rs.getInt("VNUM"));
			}
		} finally {
			try { ps.close(); } catch(Exception e) {}
		}
		return vo;
	} // end of searchByPK
	

} // end of VideoDAO 클래스

 

◆ 대여관리 탭 소스코드 ◆

<RentVO 클래스>

더보기
package videoshop.model.vo;

public class RentVO {
	// 멤버변수 - Video 테이블의 컬럼과 매칭하도록 선언
	int rnum;
	int vnum;
	String tel;
	String rent_data;
	String return_date;
	
	public RentVO () {
		
	}

	public int getRnum() {
		return rnum;
	}

	public void setRnum(int rnum) {
		this.rnum = rnum;
	}

	public int getVnum() {
		return vnum;
	}

	public void setVnum(int vnum) {
		this.vnum = vnum;
	}

	public String getTel() {
		return tel;
	}

	public void setTel(String tel) {
		this.tel = tel;
	}

	public String getRent_data() {
		return rent_data;
	}

	public void setRent_data(String rent_data) {
		this.rent_data = rent_data;
	}

	public String getReturn_date() {
		return return_date;
	}

	public void setReturn_date(String return_date) {
		this.return_date = return_date;
	}

}

<RentView 클래스>

더보기
package  videoshop.view;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.JButton;
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.border.TitledBorder;
import javax.swing.table.AbstractTableModel;

import videoshop.model.RentDAO;
import videoshop.model.vo.CustomerVO;
import videoshop.model.vo.RentVO;

public class RentView extends JPanel 
{
	// 멤버 변수
	JTextField tfRentTel, tfRentCustName, tfRentVideoNum, tfReturnVideoNum;
	JButton bRent, bReturn;
	JTable tableRent;
	RentTableModel tableRecentList;
	
	RentDAO dao;
	
	/** constructor method **/
	public RentView(){
		addLayout();
		eventProc();
		connectDB();
		select();
	} // end of 생성자함수
	
	/** DB연결 **/
	public void connectDB() {
		try {
			dao = new RentDAO();
			System.out.println("DB 연결성공 - 대여관리");
		} catch (Exception e) {
			System.out.println("DB 연결실패 - 대여관리:" + e.toString());
		}
	} // end of connectDB
	
	/** 버튼 이벤트와 객체 연결 **/
	public void eventProc() {
		ButtonEventHandler hdlr = new ButtonEventHandler();
		bRent.addActionListener(hdlr);
		bReturn.addActionListener(hdlr);
		tfRentTel.addActionListener(hdlr);
	} // end of eventProc
	
	/** 버튼 이벤트 핸들러를 만들기 위한 이너클래스 **/
	class ButtonEventHandler implements ActionListener {
		public void actionPerformed(ActionEvent ev) {
			Object o = ev.getSource();
			
			if (o==bRent) {
				rentVideo();
				clearTextField();
				select();
			} else if (o==bReturn) {
				returnVideo();
				clearTextField();
				select();
			} else if (o==tfRentTel) {
				searchByTel();
			}
		}
	}// end of 버튼 이벤트 핸들러
	
	/** 입력창 초기화 **/
	public void clearTextField() {
		tfRentTel.setText(null);
		tfRentCustName.setText(null);
		tfRentVideoNum.setText(null);
		tfReturnVideoNum.setText(null);
	} // end of clearTextField
	
	/**
	 * 함수명 : rentVideo
	 * 인자 : 없음
	 * 리턴형 : void
	 * 역할 : 화면에 입력한 고객의 전화번호와 비디오번호를 받아서 대여 관리 테이블에 추가하는 역할
	 */
	public void rentVideo() {
		String tel = tfRentTel.getText();
		String vNum = tfRentVideoNum.getText();
		try {
			dao.rent(tel, vNum);
		} catch (Exception e) {
			System.out.println("대여실패: " + e.toString());
			e.printStackTrace();
		}
	} // end of rentVideo
	
	/**
	 * 함수명 : returnVideo
	 * 인자 : 없음
	 * 리턴형 : void
	 * 역할 : 화면에 입력한 비디오번호를 받아서 대여 관리 테이블에서 반납일을 오늘날짜로 입력
	 */
	public void returnVideo() {
		String vNum = tfReturnVideoNum.getText();
		try {
			dao.returnV(vNum);
		} catch (Exception e) {
			System.out.println("반납실패: " + e.toString());
			e.printStackTrace();
		}
	} // end of returnVideo
	
	
	/** 전화번호 텍스트 입력 후 엔터시 호출 될 메소드 **/
	void searchByTel() {
		String tel = tfRentTel.getText();
		try {
			CustomerVO vo = dao.searchTel(tel);
			tfRentCustName.setText(vo.getCustName());
		} catch (Exception e) {
			System.out.println("전화번호 검색 실패: " + e.toString());
			e.printStackTrace();
		}
	} // end of searchByTel
	
	/** 미납목록을 화면에 출력하는 메소드 **/
	void select() {
		try {
			ArrayList data = dao.select();
			tableRecentList.data = data;
			tableRent.setModel(tableRecentList);
			tableRecentList.fireTableDataChanged();
		} catch (Exception e) {
			System.out.println("미납목록 검색 실패");
			e.printStackTrace();
		}
	} // end of select
	
	// 화면 구성
	public void addLayout() {
		tfRentTel			= new JTextField(20);
		tfRentCustName		= new JTextField(20);
		tfRentVideoNum		= new JTextField(20);
		tfReturnVideoNum	= new JTextField(20);
		
		bRent				= new JButton("대여");
		bReturn				= new JButton("반납");
		
		tableRecentList		= new RentTableModel();
		tableRent			= new JTable(tableRecentList);
		
		//**********************************************//
		setLayout(new BorderLayout());
		JPanel pNorth		= new JPanel();
		pNorth.setLayout(new GridLayout(1,2));
			
			JPanel pNorthLeft = new JPanel();
			pNorthLeft.setBorder(new TitledBorder("대여"));
			pNorthLeft.setLayout(new GridLayout(4,2));
			pNorthLeft.add(new JLabel("전 화 번 호"));
			pNorthLeft.add(tfRentTel);
			pNorthLeft.add(new JLabel("고  객  명"));
			pNorthLeft.add(tfRentCustName);
			pNorthLeft.add(new JLabel("비디오 번호"));
			pNorthLeft.add(tfRentVideoNum);
			pNorthLeft.add(bRent);
			
			JPanel pNorthRight= new JPanel();
			pNorthRight.setBorder(new TitledBorder("반납"));
			pNorthRight.add(new JLabel("비디오 번호"));
			pNorthRight.add(tfReturnVideoNum);
			pNorthRight.add(bReturn);
			
			pNorth.add(pNorthLeft);
			pNorth.add(pNorthRight);
			
		JPanel pCenter		= new JPanel();
		pCenter.setLayout(new BorderLayout());
			pCenter.add(new JScrollPane(tableRent), BorderLayout.CENTER);
		
		add(pNorth, BorderLayout.NORTH);
		add(pCenter, BorderLayout.CENTER);
		
	} // end of addLayout
	
	
	/** JTable 관리를 위한 TableModel 이너클래스 **/ 
	class RentTableModel extends AbstractTableModel {
		
		ArrayList data = new ArrayList();
		String [] columnNames
		= {"비디오번호", "비디오제목", "고 객 명", "전화번호", "반납예정일", "반납여부"};

		public int getRowCount() {
			return data.size();
		}
		public int getColumnCount() {
			return columnNames.length;
		}
		public Object getValueAt(int row, int col) {
			ArrayList temp = (ArrayList)data.get(row);
			return temp.get(col);
		}
		public String getColumnName(int col) {
			return columnNames[col];
		}
	} // end of RentTableModel

} // end of RentView 클래스

<RentDAO 클래스>

더보기
package videoshop.model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;

import videoshop.model.vo.CustomerVO;

public class RentDAO {
	
	Connection con;

	/** constructor method **/
	public RentDAO () throws Exception {
		con = DBcon.getInstance();
	} // end of 생성자 함수
	
	/**
	 * 함수명 : rent
	 * 인자 : String tel, String vNum
	 * 리턴형 : void
	 * 역할 : 전화번호와 비디오번호를 바탕으로 rent 테이블에 SQL로 입력하는 역할
	 */
	public void rent(String tel, String vNum) throws Exception {
		
		PreparedStatement ps = null;
		try {
			String sql = "INSERT INTO rent (RNUM, TEL, VNUM, RENT_DATE) "
				+ "VALUES (rent_num.nextval, ?, ?, sysdate)";
			ps = con.prepareStatement(sql);
			ps.setString(1,  tel);
			ps.setString(2, vNum);
			int result = ps.executeUpdate();
			System.out.println(result+"행을 입력");
		} finally {
			try { ps.close(); } catch(Exception e) {}
		}
	} // end of rent
	
	
	/**
	 * 함수명 : returnV
	 * 인자 : String vNum
	 * 리턴형 : void
	 * 역할 : 비디오번호를 바탕으로 반납날짜를 입력하는 SQL을 전송하는 역할
	 */
	public void returnV(String vNum) throws Exception {
		PreparedStatement ps = null;
		try {
			String sql = "UPDATE rent SET return_date=sysdate "
					+ "WHERE vnum=? AND return_date is null";
			System.out.println(sql);
			ps = con.prepareStatement(sql);
			ps.setString(1, vNum);
			int result = ps.executeUpdate();
			System.out.println(result+"행을 입력");
			
		} finally {
			try { ps.close(); } catch(Exception e) {}
		}
	} // end of returnV
	
	
	/** 
	 * 함수명 : searchTel
	 * 인자 : String tel
	 * 리턴형 : CustomerVO vo
	 * 역할 : 전화번호를 바탕으로 SQL에서 이름을 가져오는 역할
	 */
	public CustomerVO searchTel (String tel) throws Exception {
		CustomerVO vo = new CustomerVO();
		PreparedStatement ps = null;
		
		try {
			String sql = "SELECT * FROM member WHERE tel = ?";
			ps = con.prepareStatement(sql);
			ps.setString(1, tel);
			ResultSet rs = ps.executeQuery();
			if (rs.next()) {
				vo.setCustName(rs.getString("NAME"));
			}
		} finally {
			try { ps.close(); } catch(Exception e) {}
		}
		return vo;
	} // end of searchTel

	
	/**
	 * 함수명 : select
	 * 인자 : 
	 * 리턴형 : 
	 * 역할 : 화면에 미납목록이 출력되도록 SQL에서 데이터를 가져오는 역할
	 */
	public ArrayList select() throws Exception {
		String sql = "SELECT r.vnum vnum, v.title title, m.name name, "
				+ "r.tel tel, r.rent_date+3 rent_date, "
				+ "r.return_date return_date "
				+ "FROM rent r INNER JOIN member m ON r.tel=m.tel "
				+ "INNER JOIN video v ON r.vnum=v.vnum "
				+ "WHERE r.return_date is null";	
		// sql문 내에 자바의 변수를 사용할 경우에는 자동 '' 문제로 ps를 사용할 수 없다. 
		System.out.println(sql);
		
		Statement st = con.createStatement();
		ResultSet rs = st.executeQuery(sql);
		ArrayList data = new ArrayList();
		while (rs.next()) {
			ArrayList temp = new ArrayList();
			temp.add(rs.getInt("vnum"));
			temp.add(rs.getString("title"));
			temp.add(rs.getString("name"));
			temp.add(rs.getString("tel"));
			temp.add(rs.getString("rent_date"));
			temp.add(rs.getString("return_date"));
			data.add(temp);
		}
		rs.close();
		st.close();
		return data;
	} // end of select
	
	
} // end of RentDAO 클래스

 

 

 

2. 싱글톤 패턴 (Singleton Pattern)

 : 고정된 메모리 영역을 얻으면서 한 번의 new로 인스턴스를 사용하기 떄문에 메모리 낭비를 방지할 수 있다. 또한 싱글톤으로 만들어진 클래스의 인스턴스는 전역 인스턴스이기 때문에 다른 클래스의 인스턴스들이 데이터를 공유하기 쉽다.

 : Database Connection 처럼 공통된 객체를 여러개 생성해서 사용해야 하는 상황에서 많이 사용한다. 

   ex) 스레드풀, 캐시, 대화상자, 사용자 설정, 레지스트리 설정, 로그 기록 객체, 안드로이드 앱 등

 : 인스턴스가 절대적으로 한 개만 존재하는 것을 보증하고 싶을 경우에 사용한다. 

 : 두 번째 이용시부터는 객체 로딩 시간이 현저하게 줄어 성능이 좋아지는 장점이 있다. 

 : 단점! : 싱글톤 인스턴스가 너무 많은 일을 하거나 많은 데이터를 공유시킬 경우, 다른 클래스의 인스턴스들 간에 결합도가 높아져 객체 지향 설계 원칙에 어긋날 수 있다. 또한 수정작업과 테스트에 어려움을 겪을 수 있다. 멀티스레드 환경에서 동기화 처리를 하지 않을 경우, 인스턴스가 두 개 생성되는 등의 상황이 발생할 수 있다. 

 

◆ 비디오샵에서의 싱글톤 사용 ◆

(1) 3개의 DAO마다 각각 Connection con을 new로 생성하는 것은 비효율적이다. 

   -> 단 한 번만 con을 생성하여 DAO들이 공유하고자 함
   -> 공유 = static 처리 필요함
(2) Connection con이 단 한 번 생성될 클래스 DBcon을 만든다. 
(3) DBcon의 생성자 함수에서 드라이버를 로딩한다. (예외던지기 처리도 해줌)

public class DBcon {

	static Connection con;
	String url = "jdbc:oracle:thin:@192.168.0.17:1521:orcl";
	String user = "scott";
	String pass = "tiger";
	
	private DBcon() throws Exception {
		Class.forName("oracle.jdbc.driver.OracleDriver");
		con = DriverManager.getConnection(url,user, pass);	
	}
}

(4) getInstancce() 라는 메소드를 생성하고, 3개의 DAO에 있는 connectDB()에서 getInstance()를 호출하게 한다. 
<DBcon 클래스>

public Connection getInstance() throws Exception {
	DBcon = new DBcon();
	return con;
}

<<DAO 클래스>

void  connectDB() throws Exception {
	DBcon db = new DBcon();
	con = db.getInstance();
}

(5) 여전히 DAO에서 new DBcon()을 하면 총 3번 new를 하는 상태이다. 단 한 번만 new를 하기 위해 getInstance()에서 new DBcon하는 조건문을 작성한다. 
   -> 조건 : con이 없을 때는 con == null으로 알 수 있다.

public Connection getInstance() throws Exception {
	if (con == null) new DBcon();
	return con;
}

그리고 단 한 번 메모리에 띄운 것을 공유하기 위해 static 처리를 한다. 

Connection con
---> static Connection con;

public Connection getInstance() throws Exception 
---> public static Connection getInstance() throws Exception

각각의 DAO에서 이미 생성된 con을 얻어오려면 클래스명을 사용하여 메소드를 호출하면 된다. 

con = db.getInstance(); 
---> con = DBcon.getInstance();

(6) 최종적인 DAO의 생성자 함수 형태 

public RentDAO () throws Exception {
	con = DBcon.getInstance();
}

 --> DBcon에서 생성한 con을 DAO들이 공유하여 호출한다. 

 

 

 

3. jfreechart

www.jfree.org/jfreechart/ 에서 도움말(Docs)을 확인할 수 있다. 

※ 차트를 만들고자할 때 사용

 

(0) DB와 연결 - Database 클래스

<Database 클래스 소스 코드>

더보기
package jfreechart;

import java.sql.*;
import java.util.*;

public class Database {

	String URL = "jdbc:oracle:thin:@192.168.0.17:1521:orcl";
	String USER ="scott";
	String PASS = "tiger";

	public ArrayList<ArrayList> getData() {

		ArrayList<ArrayList> data = new ArrayList<ArrayList>();
		try{
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection con = DriverManager.getConnection(URL, USER , PASS);	
			
			//***************************************************************
			String sql = "SELECT ename, sal FROM emp WHERE sal is not null AND rownum<11 ORDER BY sal DESC";
			//***************************************************************
			
			PreparedStatement stmt = con.prepareStatement( sql );	

			ResultSet rset = stmt.executeQuery();

			
			while( rset.next() ){
				ArrayList temp = new ArrayList();
				temp.add( rset.getInt("sal"));				//****************
				temp.add( rset.getString("ename"));		//****************		
				data.add(temp);
			}
			rset.close();
			stmt.close();
			con.close();
		} catch(Exception ex){
			System.out.println("에러 : " + ex.getMessage() );
		}
		return data;
	}
}

 

(0) 화면 출력을 위해 어떤 그래프를 출력할지 객체를 선택 - MyFrame 클래스

<MyFrame 클래스 소스 코드>

더보기
package jfreechart;

import javax.swing.JFrame;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;

public class MyFrame extends JFrame {

	// 우리가 만드는 화면 
	MyFrame(){
		 // *******************************************************
//		 ChartA demo = new ChartA();   					 	// (1) 정해진 값으로 차트
//		 ChartB demo = new ChartB();		 				// (2) DB에서 가져온 값으로 차트 
		 PolylineBarChart demo = new PolylineBarChart();	// (3) bar그래프와 line그래프가 겹쳐진 차트
         JFreeChart chart = demo.getChart();     
         ChartPanel chartPanel=new ChartPanel(chart); 
         				// JFreeChart는 ChartPanel이나 ChartFrame에만 붙일 수 있다.
         				// 차트만 출력하려면 ChartFrame에 붙여서 바로 출력하거나
         				// 기존의 화면에 보이게 하려면 ChartPanel에 붙이고 다시 우리 화면 JPanel에 붙인다. 
         add(chartPanel);
         setSize(800,400); 
         setVisible(true);
         setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public static void main(String[] args) {
		MyFrame my = new MyFrame();
	}

}

 

(1) 이클립스에서 직접 데이터를 입력하여 차트를 생성하는 경우 - ChartA 클래스

<ChartA 클래스 소스 코드>

더보기
package jfreechart;

import java.awt.*;

import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.labels.*;
import org.jfree.chart.plot.*;
import org.jfree.chart.renderer.category.*;
import org.jfree.chart.title.*;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.*;

public class ChartA {
    public JFreeChart getChart() {
        
        // 데이터 생성
        DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 
 
        //------------------------------------------------------------------
        // 데이터 입력 ( 값, 범례, 카테고리 )
        dataset.addValue(1.0, "S1", "1월");
        dataset.addValue(4.0, "S1", "2월");
        dataset.addValue(3.0, "S1", "3월");
        dataset.addValue(5.0, "S1", "4월");
        dataset.addValue(5.0, "S1", "5월");
        dataset.addValue(7.0, "S1", "6월");
        dataset.addValue(7.0, "S1", "7월");
        dataset.addValue(8.0, "S1", "8월");
        dataset.addValue(5.0, "S1", "9월");
        dataset.addValue(  0, "S1", "10월");
        dataset.addValue(6.0, "S1", "11월");
        dataset.addValue(3.0, "S1", "12월");
        // 위 부분을 반복문으로 만들었으면 좋겠다는 강한 느낌 ^^
        //------------------------------------------------------------------
        
        // 렌더링 생성 및 세팅
        // 렌더링 생성
        final BarRenderer renderer = new BarRenderer();
     
        // 공통 옵션 정의
        final CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator();
        final ItemLabelPosition p_center = new ItemLabelPosition(
                ItemLabelAnchor.CENTER, TextAnchor.CENTER
            );
        final ItemLabelPosition p_below = new ItemLabelPosition(
                     ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_LEFT
                     );
        Font f = new Font("Gulim", Font.BOLD, 14);
        Font axisF = new Font("Gulim", Font.PLAIN, 14);
       
        // 렌더링 세팅
        // 그래프 1
        renderer.setBaseItemLabelGenerator(generator);
        renderer.setBaseItemLabelsVisible(true);
        renderer.setBasePositiveItemLabelPosition(p_center);
        renderer.setBaseItemLabelFont(f);
        renderer.setSeriesPaint(0, new Color(0,162,255));
 
        // plot 생성
        final CategoryPlot plot = new CategoryPlot();
       
        // plot 에 데이터 적재
        plot.setDataset(dataset);
        plot.setRenderer(renderer);
 
        // plot 기본 설정
        plot.setOrientation(PlotOrientation.VERTICAL);       // 그래프 표시 방향
        plot.setRangeGridlinesVisible(true);                 // X축 가이드 라인 표시여부
        plot.setDomainGridlinesVisible(true);                // Y축 가이드 라인 표시여부
 
        // 렌더링 순서 정의 : dataset 등록 순서대로 렌더링 ( 즉, 먼저 등록한게 아래로 깔림 )
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
       
        // X축 세팅
        plot.setDomainAxis(new CategoryAxis());          	// X축 종류 설정
        plot.getDomainAxis().setTickLabelFont(axisF); 		// X축 눈금라벨 폰트 조정
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.STANDARD);       // 카테고리 라벨 위치 조정
 
        // Y축 세팅
        plot.setRangeAxis(new NumberAxis());             	// Y축 종류 설정
        plot.getRangeAxis().setTickLabelFont(axisF);  		// Y축 눈금라벨 폰트 조정
       
        // 세팅된 plot을 바탕으로 chart 생성
        final JFreeChart chart = new JFreeChart(plot);
        chart.setTitle(" 우리들의 차트 "); 
        TextTitle copyright = new TextTitle("월별 입사 현황 ", new Font("SansSerif", Font.PLAIN, 9));
        copyright.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        chart.addSubtitle(copyright);  
        return chart;
    }
}

 

(2) 오라클에서 가져온 데이터로 차트를 생성하는 경우 - ChartB 클래스

<ChartB 클래스 소스 코드>

더보기
package jfreechart;

import java.awt.Color;
import java.awt.Font;
import java.util.ArrayList;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.CategoryItemLabelGenerator;
import org.jfree.chart.labels.ItemLabelAnchor;
import org.jfree.chart.labels.ItemLabelPosition;
import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.DatasetRenderingOrder;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.DefaultCategoryDataset;
import org.jfree.ui.HorizontalAlignment;
import org.jfree.ui.TextAnchor;

public class ChartB {
    public JFreeChart getChart() {
        
        // 데이터 생성
        DefaultCategoryDataset dataset = new DefaultCategoryDataset(); 
 
        //------------------------------------------------------------------
        // 데이터 입력 ( 값, 범례, 카테고리 )
        Database db = new Database();
        ArrayList<ArrayList> data = db.getData();
        for(ArrayList temp : data) {
        	int value = (Integer) temp.get(0);
        	String cate = (String) temp.get(1);
        	dataset.addValue(value, "월별",  cate);
        }
        //------------------------------------------------------------------
        
        // 렌더링 생성 및 세팅
        // 렌더링 생성
        final BarRenderer renderer = new BarRenderer();
     
        // 공통 옵션 정의
        final CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator();
        final ItemLabelPosition p_center = new ItemLabelPosition(
                ItemLabelAnchor.CENTER, TextAnchor.CENTER
            );
        final ItemLabelPosition p_below = new ItemLabelPosition(
                     ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_LEFT
                     );
        Font f = new Font("Gulim", Font.BOLD, 14);
        Font axisF = new Font("Gulim", Font.PLAIN, 14);
       
        // 렌더링 세팅
        // 그래프 1
        renderer.setBaseItemLabelGenerator(generator);
        renderer.setBaseItemLabelsVisible(true);
        renderer.setBasePositiveItemLabelPosition(p_center);
        renderer.setBaseItemLabelFont(f);
        renderer.setSeriesPaint(0, new Color(0,162,255));
 
        // plot 생성
        final CategoryPlot plot = new CategoryPlot();
       
        // plot 에 데이터 적재
        plot.setDataset(dataset);
        plot.setRenderer(renderer);
 
        // plot 기본 설정
        plot.setOrientation(PlotOrientation.VERTICAL);       // 그래프 표시 방향
        plot.setRangeGridlinesVisible(true);                 // X축 가이드 라인 표시여부
        plot.setDomainGridlinesVisible(true);                // Y축 가이드 라인 표시여부
 
        // 렌더링 순서 정의 : dataset 등록 순서대로 렌더링 ( 즉, 먼저 등록한게 아래로 깔림 )
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
       
        // X축 세팅
        plot.setDomainAxis(new CategoryAxis());           	// X축 종류 설정
        plot.getDomainAxis().setTickLabelFont(axisF); 		// X축 눈금라벨 폰트 조정
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.STANDARD);   
        													// 카테고리 라벨 위치 조정
 
        // Y축 세팅
        plot.setRangeAxis(new NumberAxis());              	// Y축 종류 설정
        plot.getRangeAxis().setTickLabelFont(axisF);  		// Y축 눈금라벨 폰트 조정
       
        // 세팅된 plot을 바탕으로 chart 생성
        final JFreeChart chart = new JFreeChart(plot);
        chart.setTitle(" 우리들의 차트 "); 
        TextTitle copyright = new TextTitle("월별 입사 현황", new Font("SansSerif", Font.PLAIN, 9));
        copyright.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        chart.addSubtitle(copyright);  
        return chart;
    }
}

 

(3) bar 그래프와 line 그래프가 함께 출력(데이터는 이클립스에서 입력함) - PolylineBarChart 클래스

<PolylineBarChart 클래스 소스 코드>

더보기
package jfreechart;

import java.awt.*;

import org.jfree.chart.*;
import org.jfree.chart.axis.*;
import org.jfree.chart.labels.*;
import org.jfree.chart.plot.*;

import org.jfree.chart.renderer.category.*;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.category.DefaultCategoryDataset;

import org.jfree.ui.*;
 

public class PolylineBarChart {
 
    public JFreeChart getChart() {
      
        // 데이터 생성
        DefaultCategoryDataset dataset1 = new DefaultCategoryDataset();     // bar chart 1
        DefaultCategoryDataset dataset12 = new DefaultCategoryDataset();    // bar chart 2
        DefaultCategoryDataset dataset2 = new DefaultCategoryDataset();     // line chart 1
 
        // 데이터 입력 ( 값, 범례, 카테고리 )
        // 그래프 1       
        dataset1.addValue(1.0, "S1", "1월");
        dataset1.addValue(4.0, "S1", "2월");
        dataset1.addValue(3.0, "S1", "3월");
        dataset1.addValue(5.0, "S1", "4월");
        dataset1.addValue(5.0, "S1", "5월");
        dataset1.addValue(7.0, "S1", "6월");
        dataset1.addValue(7.0, "S1", "7월");
        dataset1.addValue(8.0, "S1", "8월");
        dataset1.addValue(0, "S1", "9월");
        dataset1.addValue(0, "S1", "10월");
        dataset1.addValue(0, "S1", "11월");
        dataset1.addValue(0, "S1", "12월");
 
        // 그래프 2       
        dataset12.addValue(0, "S2", "1월");
        dataset12.addValue(0, "S2", "2월");
        dataset12.addValue(0, "S2", "3월");
        dataset12.addValue(0, "S2", "4월");
        dataset12.addValue(0, "S2", "5월");
        dataset12.addValue(0, "S2", "6월");
        dataset12.addValue(0, "S2", "7월");
        dataset12.addValue(0, "S2", "8월");
        dataset12.addValue(6.0, "S2", "9월");
        dataset12.addValue(4.0, "S2", "10월");
        dataset12.addValue(8.0, "S2", "11월");
        dataset12.addValue(7.0, "S2", "12월");

 
        // 그래프 3       
        dataset2.addValue(9.0, "T1", "1월");
        dataset2.addValue(7.0, "T1", "2월");
        dataset2.addValue(2.0, "T1", "3월");
        dataset2.addValue(6.0, "T1", "4월");
        dataset2.addValue(6.0, "T1", "5월");
        dataset2.addValue(9.0, "T1", "6월");
        dataset2.addValue(5.0, "T1", "7월");
        dataset2.addValue(4.0, "T1", "8월");
        dataset2.addValue(8.0, "T1", "9월");
        dataset2.addValue(8.0, "T1", "10월");
        dataset2.addValue(8.0, "T1", "11월");
        dataset2.addValue(8.0, "T1", "12월");
 
        // 렌더링 생성 및 세팅
        // 렌더링 생성
        final BarRenderer renderer = new BarRenderer();
        final BarRenderer renderer12 = new BarRenderer();
        final LineAndShapeRenderer renderer2 = new LineAndShapeRenderer();
       
        // 공통 옵션 정의
        final CategoryItemLabelGenerator generator = new StandardCategoryItemLabelGenerator();
        final ItemLabelPosition p_center = new ItemLabelPosition(
                ItemLabelAnchor.CENTER, TextAnchor.CENTER
            );
        final ItemLabelPosition p_below = new ItemLabelPosition(
                     ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_LEFT
                     );
        Font f = new Font("Gulim", Font.BOLD, 14);
        Font axisF = new Font("Gulim", Font.PLAIN, 14);
       
        // 렌더링 세팅
        // 그래프 1
        renderer.setBaseItemLabelGenerator(generator);
        renderer.setBaseItemLabelsVisible(true);
        renderer.setBasePositiveItemLabelPosition(p_center);
        renderer.setBaseItemLabelFont(f);
        renderer.setSeriesPaint(0, new Color(0,162,255));
 
        // 그래프 2       
        renderer12.setSeriesPaint(0, new Color(232,168,255));
        renderer12.setBaseItemLabelFont(f);
        renderer12.setBasePositiveItemLabelPosition(p_center);
        renderer12.setBaseItemLabelGenerator(generator);
        renderer12.setBaseItemLabelsVisible(true);
       
        // 그래프 3       
        renderer2.setBaseItemLabelGenerator(generator);
        renderer2.setBaseItemLabelsVisible(true);
        renderer2.setBaseShapesVisible(true);
        renderer2.setDrawOutlines(true);
        renderer2.setUseFillPaint(true);
        renderer2.setBaseFillPaint(Color.WHITE);
        renderer2.setBaseItemLabelFont(f);
        renderer2.setBasePositiveItemLabelPosition(p_below);
        renderer2.setSeriesPaint(0,new Color(219,121,22));
        renderer2.setSeriesStroke(0,new BasicStroke(
                                               2.0f,
                                               BasicStroke.CAP_ROUND,
                                               BasicStroke.JOIN_ROUND,
                                               3.0f)
        );
       
        // plot 생성
        final CategoryPlot plot = new CategoryPlot();
       
        // plot 에 데이터 적재
        plot.setDataset(dataset1);
        plot.setRenderer(renderer);
        plot.setDataset(1,dataset12);
        plot.setRenderer(1,renderer12);
        plot.setDataset(2, dataset2);
        plot.setRenderer(2, renderer2);
 
        // plot 기본 설정
        plot.setOrientation(PlotOrientation.VERTICAL);      // 그래프 표시 방향
        plot.setRangeGridlinesVisible(true);                // X축 가이드 라인 표시여부
        plot.setDomainGridlinesVisible(true);               // Y축 가이드 라인 표시여부
 
        // 렌더링 순서 정의 : dataset 등록 순서대로 렌더링 ( 즉, 먼저 등록한게 아래로 깔림 )
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);
       
        // X축 세팅
        plot.setDomainAxis(new CategoryAxis());         	// X축 종류 설정
        plot.getDomainAxis().setTickLabelFont(axisF); 		// X축 눈금라벨 폰트 조정
        plot.getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.STANDARD);       // 카테고리 라벨 위치 조정
 
        // Y축 세팅
        plot.setRangeAxis(new NumberAxis());            	// Y축 종류 설정
        plot.getRangeAxis().setTickLabelFont(axisF);  		// Y축 눈금라벨 폰트 조정
       
        // 세팅된 plot을 바탕으로 chart 생성
        final JFreeChart chart = new JFreeChart(plot);
        chart.setTitle("Overlaid Bar Chart");				// 차트 타이틀
        TextTitle copyright = new TextTitle("JFreeChart WaferMapPlot", new Font("SansSerif", Font.PLAIN, 9));
        copyright.setHorizontalAlignment(HorizontalAlignment.RIGHT);
        chart.addSubtitle(copyright);  						// 차트 서브 타이틀
        return chart;
    }
    
    public static void main(final String[] args) {
        	  PolylineBarChart demo = new PolylineBarChart();
              JFreeChart chart = demo.getChart();
              ChartFrame frame1=new ChartFrame("Bar Chart",chart);
              frame1.setSize(800,400); 
              frame1.setVisible(true);
     }
}

 

 

 

 

 

 

 

 

반응형

'교육과정 > KOSMO' 카테고리의 다른 글

Day31  (0) 2020.11.12
Day30  (0) 2020.11.11
Day28  (0) 2020.11.04
Day27  (0) 2020.11.03
Day26  (0) 2020.11.02