Crescendo Code

4월 6일 (목) - [JTextArea, JPasswordField, JCheckBox, JRadioButton, DB연동 클래스 분할] 본문

KIC 백엔드 수업

4월 6일 (목) - [JTextArea, JPasswordField, JCheckBox, JRadioButton, DB연동 클래스 분할]

Crecok 2023. 4. 6. 17:39
반응형

◆ 이전 개념 정리

 

▶ UI 구축 (목적에 맞게 구성)

- CUI : 명령 프롬프트에서 실행

- GUI : 그래픽이 있는 프로그램

   - 2D Graphic의 개념 ( 선/면, 색상, 폰트 ... ) → UI 제작 → GUI

 

▶ Java로 GUI를 사용할 수 있는 라이브러리

- AWT / Swing

- Java FX

- Swt

 

▶ AWT / Swing

- 컨테이너 : 뭔가를 담을 수 있는 상자 개념

   - Window → JFrame (Frame은 AWT) → JDialog → JPanel

   - Layout Manager ( 컨테이너 위에 컴포넌트를 설치 )

- 컴포넌트(위젯)

 

▶ 디자인 작성 순서

- Window Builder - 이클립스 Plug-in

- Window Builder에서 처리 ( Window Builder답게 코딩. 커스텀 코딩은 해석하지 못할 수도 있음 )

  1. 컨테이너 ( JFrame / JDialog )

  2. Layout Manager ( null - 좌표중심 배치 )

  3. 컴포넌트

  4. 이벤트

- 기타

  5. 이벤트별 코딩

 

- 내일 (금) 11시 10분 SQL 퀴즈 + 캡쳐 화면 (SQL) 있을 예정


◆ WindowBuilder 사용 시 주의점

 

▶ Bounds 속성

- Properties의 Bounds 속성을 누르면 구체적인 좌표와 크기를 조절할 수 있다.

 

 

▶ Variable 속성

- 변수 지정시 지역변수 여부를 확인한다.


 

예제 1. Windowbuilder를 이용하여 아래 그림과 같은 주민등록번호 검사기 프로그램 제작

JButton btn = new JButton( "주민번호검사" );
btn.addMouseListener(new MouseAdapter() {
	@Override
	public void mouseClicked(MouseEvent e) {
			
		String juminBefore = textField1.getText();
		String juminAfter = textField2.getText();
			
		// 입력길이 검사 (O)
		// 입력 값 검사 (필요한 작업)
			
		if ( juminBefore.length() != 6 || juminAfter.length() != 7 ) {
			lbl.setText( "주민등록번호 양식에 맞춰 입력해주세요" );
			textField1.setText( "" );
			textField2.setText( "" );
		} else {
				
			String strJumin = juminBefore + juminAfter;
			int[] bits = { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5 };
			int sum = 0;
			for( int i=0; i<bits.length; i++ ) {
				sum += Integer.parseInt( strJumin.substring(i, i+1)) * bits[i];
			}
			int resultNum = ( 11 - ( sum % 11 )) % 10;
			int lastNum = Integer.parseInt( strJumin.substring(12, 13) );
			
			if ( lastNum == resultNum ) {
				lbl.setText( "결과 : 정상" );
			} else {
				lbl.setText( "결과 : 비정상" );
			}
		}
	}
}

- 코드는 마우스클릭 이벤트 부분만 기재했다.


◆ JTextArea

- 단순 여러 줄 입력

- JLabel을 대신해서 여러 줄 출력이 가능 (많이 사용)

   → TextArea 안에 여러 줄의 데이터 입력 후 Properties의 editable을 false로 지정한다.

editable 속성을 false로 지정하면 수정이 불가능하다. (Label 화)

- setText() : 기존 내용을 지우면서 작성된 텍스트를 출력한다.

- append() : 기존 내용에 추가하여 작성된 텍스트를 출력한다.

- textArea.append( "new text" + System.lineSeparator() ) 와 같이 줄바꿈을 적용 할 수도 있다.

 

 

▶ scollPane (스크롤바) 추가

Textarea - Surround with - javax.swing.JScrollPane

- 스크롤바를 추가하면 scrollPane 항목이 생긴다.

- horizontalScrollBarPolicy와 verticalScrollBarPolicy의 옵션값을 ALWAYS로 바꾸면 스크롤바를 항시 표시할 수 있다.

 

 

▶ JPanel (border) 추가

- 영역을 지정할 컴포넌트들을 그룹으로 선택한 뒤 JPanel을 적용하면 선택 영역을 그룹으로 묶을 수 있다.

 

 

예제 2. WindowBuilder와 소스코드를 이용하여 시작단과 끝단 입력 시 조건에 따라 구구단이 출력되는 프로그램 제작

JButton btnNewButton = new JButton("구구단 출력");
btnNewButton.addMouseListener(new MouseAdapter() {
	@Override
	public void mouseClicked(MouseEvent e) {
		
		int startDan = Integer.parseInt(textField1.getText());
		int endDan = Integer.parseInt(textField2.getText());
		
		// 버튼 반복 사용을 위한 내용 초기화
		textArea.setText("");
		
		for (int i=startDan; i<=endDan; i++) {
			for (int j=1; j<=9; j++) {
				textArea.append( i + "x" + j + "=" + i*j + "\t" );
			}
			textArea.append( "" + System.lineSeparator() );
		}
	}
});

- 코드는 마우스클릭 이벤트 부분만 기재했다.

 

 

▶ 외부 파일을 불러올 때 WindowBuilder 화면을 여는 방법

- FileZilia - Java - Java - 강의 - JTextAreaEx03.java 자료 활용

불러온 파일 우클릭 - Open With - WindowBuilderEditor

 

 

예제 3. WindowBuilder와 DB 안의 주소록 데이터를 이용해 우편번호 검색기 프로그램 제작

JButton btn = new JButton("우편번호 검색");
btn.addMouseListener(new MouseAdapter() {
	@Override
	public void mouseClicked(MouseEvent e) {
		
		if( textField.getText().trim().length() < 2) {
			textArea.setText( "동 이름을 두 글자 이상 입력하셔야 합니다." );
		} else {
			
			textArea.setText("");
			
			String strDong = textField.getText().trim();
			
			String url = "jdbc:mariadb://localhost:3306/project";
			String user = "project";
			String password = "1234";
			
			Connection conn = null;
			PreparedStatement pstmt = null;
			ResultSet rs = null;
			
			try {
				
				Class.forName( "org.mariadb.jdbc.Driver" );
				conn = DriverManager.getConnection(url, user, password);
				
				String sql = "select zipcode, sido, gugun, dong, ri, bunji from zipcode where dong like ?";
				pstmt = conn.prepareStatement( sql );
				pstmt.setString( 1, strDong+"%");
				
				rs = pstmt.executeQuery();
				while ( rs.next() ) {
                   
					String zipcode = rs.getString( "zipcode" );
					String sido = rs.getString( "sido" );
					String gugun = rs.getString( "gugun" );
					String dong = rs.getString( "dong" );
					String ri = rs.getString( "ri" );
					String bunji = rs.getString( "bunji" );
					
					String address = String.format("[%s] %s %s %s %s %s", zipcode, sido, gugun, dong, ri, bunji );
					
					textArea.append( address + System.lineSeparator() );
					
				}
			} catch (ClassNotFoundException e1) {
				System.out.println( "[에러] " + e1.getMessage() );
			} catch (SQLException e1) {
				System.out.println( "[에러] " + e1.getMessage() );
			} finally {
				if( rs != null ) try { rs.close(); } catch( SQLException e1) {}
				if( pstmt != null ) try { pstmt.close(); } catch( SQLException e1) {}
				if( conn != null ) try { conn.close(); } catch( SQLException e1) {}
			}
		}
	}
});

- 코드는 마우스클릭 이벤트 부분만 기재했다.

 


◆ 클래스의 역할 분리

1. 한 개의 클래스로 잘게 쪼개서 사용

2. 분리 (pattern)

    - DAO, TO → MVC ( Model / View / Controller )

    - Model : 데이터 ( DAO - 데이터 연결 / DTO - 데이터 전송 )

    - View : 디자인 (UI)

    - Controller : 흐름제어

 

- DTO : Select 문과 1:1

- DAO : 생성자에서 DB와 연결 / SQL 1개당 메서드 1개

 

Q. 위 우편번호 검색기 프로그램을 3개의 클래스로 나눠서 작업

 

1. ZipcodeTO 클래스

public class ZipcodeTO {
	
	private String zipcode;
	private String sido;
	private String gugun;
	private String dong;
	private String ri;
	private String bunji;
	private String seq;
	
	public String getZipcode() {
		return zipcode;
	}
	public void setZipcode(String zipcode) {
		this.zipcode = zipcode;
	}
	public String getSido() {
		return sido;
	}
	public void setSido(String sido) {
		this.sido = sido;
	}
	public String getGugun() {
		return gugun;
	}
	public void setGugun(String gugun) {
		this.gugun = gugun;
	}
	public String getDong() {
		return dong;
	}
	public void setDong(String dong) {
		this.dong = dong;
	}
	public String getRi() {
		return ri;
	}
	public void setRi(String ri) {
		this.ri = ri;
	}
	public String getBunji() {
		return bunji;
	}
	public void setBunji(String bunji) {
		this.bunji = bunji;
	}
	public String getSeq() {
		return seq;
	}
	public void setSeq(String seq) {
		this.seq = seq;
	}

}

 

2. ZipcodeDAO 클래스

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

public class ZipcodeDAO {
	
	private Connection conn;
	public ZipcodeDAO() {
		
		String url = "jdbc:mariadb://localhost:3306/project";
		String user = "project";
		String password = "1234";
		
		try {
			Class.forName( "org.mariadb.jdbc.Driver" );
			this.conn = DriverManager.getConnection( url, user, password );
		} catch (ClassNotFoundException e) {
			System.out.println( "[에러] " + e.getMessage() );
		} catch (SQLException e) {
			System.out.println( "[에러] " + e.getMessage() );
		}
		
	}
	
	public ArrayList<ZipcodeTO> searchZipcode( String strDong ){
		
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		ArrayList<ZipcodeTO> addresses = new ArrayList<>();
		
		try {
			String sql = "select zipcode, sido, gugun, dong, ri, bunji from zipcode where dong like ?";
			pstmt = this.conn.prepareStatement( sql );
			pstmt.setString( 1, strDong + "%" );
			
			rs = pstmt.executeQuery();
			while( rs.next() ) {
				
				ZipcodeTO to = new ZipcodeTO();
				to.setZipcode( rs.getString( "zipcode") );
				to.setSido( rs.getString( "sido") );
				to.setGugun( rs.getString( "gugun") );
				to.setDong( rs.getString( "dong") );
				to.setRi( rs.getString( "ri") );
				to.setBunji( rs.getString( "bunji") );
				
				addresses.add( to );
			}
		} catch (SQLException e) {
			System.out.println( "[에러] " + e.getMessage() );
		} finally {
			if( rs != null ) try { rs.close(); } catch( SQLException e) {}
			if( pstmt != null ) try { pstmt.close(); } catch( SQLException e) {}
			if( conn != null ) try { conn.close(); } catch( SQLException e) {}
		}
		
		return addresses;
	}
}

 

3. AddressEx02 클래스

import java.awt.EventQueue;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.awt.Color;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class AddressEx02 extends JFrame {

	private JPanel contentPane;
	private JTextField textField;
	private JTextArea textArea;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {

		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					AddressEx02 frame = new AddressEx02();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public AddressEx02() {
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 800, 600);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		JPanel panel = new JPanel();
		panel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, new Color(255, 255, 255), new Color(160, 160, 160)), "\uC6B0\uD3B8\uBC88\uD638 \uD0D0\uC0C9\uAE30", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
		panel.setBounds(16, 20, 745, 69);
		contentPane.add(panel);
		panel.setLayout(null);
		
		textField = new JTextField();
		textField.setBounds(25, 25, 516, 21);
		panel.add(textField);
		textField.setColumns(10);
		
		JButton btn = new JButton("우편번호 검색");
		btn.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				
				if( textField.getText().trim().length() < 2) {
					textArea.setText( "동 이름을 두 글자 이상 입력하셔야 합니다." );
				} else {
					
					textArea.setText("");
					
					String strDong = textField.getText().trim();
					
					ZipcodeDAO dao = new ZipcodeDAO();
					ArrayList<ZipcodeTO> addresses = dao.searchZipcode( strDong );
					
					for( ZipcodeTO to : addresses ) {
						String address = String.format( "[%s] %s %s %s %s %s",
								to.getZipcode(), to.getSido(), to.getGugun(),
								to.getDong(), to.getRi(), to.getBunji() );
						
						textArea.append( address + System.lineSeparator() );
					}
					
				}
			}
		});
		
			btn.setBounds(553, 24, 176, 23);
			panel.add(btn);
			
			JScrollPane scrollPane = new JScrollPane();
			scrollPane.setBounds(22, 105, 738, 446);
			contentPane.add(scrollPane);
			
			textArea = new JTextArea();
			scrollPane.setViewportView(textArea);
	}

}

 


◆ JPasswordField

 

- echoChar 옵션으로 비밀번호를 가릴 문자를 지정할 수 있다.

 

 

Q. JPasswordField 데이터 확인하기

System.out.println( new String( passwordField.getPassword() ) );

- JPasswordField는 보이지 않을 뿐 암호화된 것은 아니다.

 

 


◆ JCheckBox

 

Q. 아래와 같이 체크박스를 설정한다.

 

Q. 체크된 목록 ( True / False 여부 ), 체크박스의 이름을 출력

public void mouseClicked(MouseEvent e) {
	System.out.println( chckbx1.isSelected() );
	System.out.println( chckbx2.isSelected() );
	System.out.println( chckbx3.isSelected() );
			
	System.out.println( chckbx1.getText() );
	System.out.println( chckbx2.getText() );
	System.out.println( chckbx3.getText() );
}

 

Q. 체크된 목록만 이름을 출력하는 소스를 작성

public void mouseClicked(MouseEvent e) {

	String result = "";
	if( chckbx1.isSelected() ) result += chckbx1.getText() + " ";
	if( chckbx2.isSelected() ) result += chckbx2.getText() + " ";
	if( chckbx3.isSelected() ) result += chckbx3.getText() + " ";
				
	System.out.println( "결과 : " + result );
				
}

 

 

Q. 전체 선택, 전체 해제 버튼을 만들고 그 기능을 구현

public void mouseClicked(MouseEvent e) {
	chckbx1.setSelected(true);
	chckbx2.setSelected(true);
	chckbx3.setSelected(true);
}
            
 public void mouseClicked(MouseEvent e) {	
	chckbx1.setSelected(false);
	chckbx2.setSelected(false);
	chckbx3.setSelected(false);		
}

 

Q. 버튼을 추가하고 클릭마다 '전체 선택', '전체 해제' 문구가 바뀌는 버튼을 구현

public void mouseClicked(MouseEvent e) {

	if( btn3.getText().equals( "전체 선택" ) ) {
		btn3.setText( "전체 해제" );
	} else {
		btn3.setText( "전체 선택" );
	}

}

 


◆ JRadioButton

 

Q. RadioButton 3개를 그룹화하여 단일 선택 버튼으로 만들기

 

Q. 새 버튼을 클릭하면 체크된 RadioButton에 해당하는 이름을 출력

public void mouseClicked(MouseEvent e) {

	String result = "";
	if( rdbtn1.isSelected() ) System.out.println(rdbtn1.getText());
	if( rdbtn2.isSelected() ) System.out.println(rdbtn2.getText());
	if( rdbtn3.isSelected() ) System.out.println(rdbtn3.getText());

}

 

예제 4. 부서이름 검색기 ( 출력 : 부서번호, 부서위치, 사원번호, 사원이름, 직책, 급여 )

- DAO / TO / 실행클래스 총 3개를 만들어서 제작

 

1. DepfSearchTO 클래스

public class DeptSearchTO {
	
	private String deptno;
	private String loc;
	private String empno;
	private String ename;
	private String job;
	private String sal;
	
	public String getDeptno() {
		return deptno;
	}
	public void setDeptno(String deptno) {
		this.deptno = deptno;
	}
	public String getLoc() {
		return loc;
	}
	public void setLoc(String loc) {
		this.loc = loc;
	}
	public String getEmpno() {
		return empno;
	}
	public void setEmpno(String empno) {
		this.empno = empno;
	}
	public String getEname() {
		return ename;
	}
	public void setEname(String ename) {
		this.ename = ename;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	public String getSal() {
		return sal;
	}
	public void setSal(String sal) {
		this.sal = sal;
	}
	
}

 

2. DeptSearchDAO 클래스

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

public class DeptSearchDAO {
	
	private Connection conn;
	public DeptSearchDAO() {
		
		String url = "jdbc:mariadb://localhost:3306/sample";
		String user = "root";
		String password = "123456";
		
		try {
			Class.forName( "org.mariadb.jdbc.Driver" );
			this.conn = DriverManager.getConnection( url, user, password );
		} catch (ClassNotFoundException e) {
			System.out.println( "[에러] " + e.getMessage() );
		} catch (SQLException e) {
			System.out.println( "[에러] " + e.getMessage() );
		}
		
	}
	
	public ArrayList<DeptSearchTO> searchZipcode( String strDept ){
		
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		
		ArrayList<DeptSearchTO> depts = new ArrayList<>();
		
		try {
			String sql = "select e.empno, e.ename, e.job, e.sal, e.deptno, d.loc from ( select * from dept where dname like ? ) d inner join emp e on (d.deptno = e.deptno);";
			pstmt = this.conn.prepareStatement( sql );
			pstmt.setString( 1, "%" + strDept + "%" );
			
			rs = pstmt.executeQuery();
			while( rs.next() ) {
				
				DeptSearchTO to = new DeptSearchTO();
				to.setEmpno( rs.getString( "empno") );
				to.setEname( rs.getString( "ename") );
				to.setJob( rs.getString( "job") );
				to.setSal( rs.getString( "sal") );
				to.setDeptno( rs.getString( "deptno") );
				to.setLoc( rs.getString( "loc") );
				
				depts.add( to );
			}
		} catch (SQLException e) {
			System.out.println( "[에러] " + e.getMessage() );
		} finally {
			if( rs != null ) try { rs.close(); } catch( SQLException e) {}
			if( pstmt != null ) try { pstmt.close(); } catch( SQLException e) {}
			if( conn != null ) try { conn.close(); } catch( SQLException e) {}
		}
		
		return depts;
	}
}

 

3. DeptSearchEx01 클래스

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JButton;
import javax.swing.border.TitledBorder;
import javax.swing.border.EtchedBorder;
import java.awt.Color;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

public class DeptSearchEx01 extends JFrame {

	private JPanel contentPane;
	private JTextField textField;
	private JTextArea textArea;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					DeptSearchEx01 frame = new DeptSearchEx01();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public DeptSearchEx01() {
		setResizable(false);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 800, 600);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		JPanel panel = new JPanel();
		panel.setBorder(new TitledBorder(new EtchedBorder(EtchedBorder.LOWERED, new Color(255, 255, 255), new Color(160, 160, 160)), "\uBD80\uC11C\uC774\uB984 \uAC80\uC0C9", TitledBorder.LEADING, TitledBorder.TOP, null, new Color(0, 0, 0)));
		panel.setBounds(16, 24, 741, 53);
		contentPane.add(panel);
		panel.setLayout(null);
		
		textField = new JTextField();
		textField.setBounds(25, 18, 552, 21);
		panel.add(textField);
		textField.setColumns(10);
		
		JButton btn = new JButton( "부서이름 검색" );
		btn.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				
				if( textField.getText().trim().length() < 2) {
					textArea.setText( "부서 이름을 두 글자 이상 입력하셔야 합니다." );
				} else {
					
					textArea.setText("");
					
					String strDept = textField.getText().trim();
					
					DeptSearchDAO dao = new DeptSearchDAO();
					ArrayList<DeptSearchTO> depts = dao.searchZipcode( strDept );
					
					for( DeptSearchTO to : depts ) {
						String dept = String.format( "%s %s %s %s %s %s",
								to.getEmpno(), to.getEname(), to.getJob(),
								to.getSal(), to.getDeptno(), to.getLoc() );
						
						textArea.append( dept + System.lineSeparator() );
					}
				}

			}
		});
		btn.setBounds(589, 17, 134, 23);
		panel.add(btn);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(26, 91, 727, 460);
		contentPane.add(scrollPane);
		
		textArea = new JTextArea();
		scrollPane.setViewportView(textArea);
	}

}

 

반응형

'KIC 백엔드 수업' 카테고리의 다른 글

4월 10일 (월) - [JTable, DAO, TO]  (0) 2023.04.10
4월 7일 (금) - []  (0) 2023.04.07
4월 5일 (수) - [UI]  (0) 2023.04.05
4월 4일 (화) - []  (0) 2023.04.04
4월 3일 (월) - []  (0) 2023.04.03
Comments