코밍이의 하루

[JAVA] 계산기 프로그램 프로젝트_2일차(기능 구현I) 본문

프로젝트 개발 프로그램/[JAVA] 계산기 프로그램

[JAVA] 계산기 프로그램 프로젝트_2일차(기능 구현I)

코밍이 2021. 7. 27. 00:53

2. 계산기 프로그램 기능 구현I

 

1) 계산기 프로그램 개발 환경

구분 내용
사용 프로그래밍 언어 JAVA
개발환경 eclipse
GUI 관련 주요 클래스 SWING,AWT
기능 관련 주요 인터페이스 ActionListener
벤치마킹 프로그램 Windows 계산기

 

2) 개발 소스

package calculator;

// GUI 구현을 위해 사용하는 클래스들(awt, swing)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Calculator extends JFrame implements ActionListener{

	JPanel p_all, p_cal, p_cont; // 객체 선언
	JButton rem, ce, c, b_space, frac, squa, root, div, seven, eight, nine, mul, four, five,
		    six, minus, one, two, three, plus, sign, zero, point, equal;// 버튼 선언
	
	JLabel process, result; // 레이블 선언
	
	String num1 , num2; // 피연산자들을 저장하는 변수
	String func; // 연산자 저장하는 변수
	String pro; // 연산 관정을 저장하는 변수
	String result_num; // 결과값을 저장하는 변수
	
	
	
	public Calculator(String title) {
		
		// 기본 프로그램 설정(제목, 크기, 위치)
		this.setTitle(title);
		this.setSize(350, 450);
		this.setLocation(800, 280);
		
		//종료(EXIT_ON_CLOSE를 사용, 없으면 작업 프로세스에 남아서 메모리만 차지함.)
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		/* 1. 배치 관리자 종류
		 * 1) FlowLayout : 왼쪽에서 오른쪽으로 배치, 오른쪽 공간 없으면 아래로 자동 배치
		 *  - 사용 예제 : FlowLatout(FlowLayout.LEFT, 10, 20); // 왼쪽 정렬, 좌우간격 10, 상하간격 20
		 * 2) BorderLayout : 상하좌우 + 중앙 5개의 영역으로 나눠 배치
		 *  - 사용 예제 : BorderLayout(30,20); //좌우간격 30, 상하간격 20
		 * 3) GridLayout : 2차원 그리드로서 n x n 으로 설정, 왼->오, 위->아래 순 배치 
		 *  - 사용 예제 : GridLayout(4,3,5,50); // 4 x 3 그리드, 좌우간격 5, 상하간격 50
		 * 4) CardLayout : 컴포넌트를 포개어 배치
		 * 5) Null : 레이아웃을 쓰지 않고 각 컴포넌트마다 수동으로 위치 설정해줄 때 사용
		 */
		
		//Panel 객체 생성
		p_all = new JPanel();
		p_cal = new JPanel();
		p_cont = new JPanel();
		
		//폰트 생성
		Font bold = new Font("맑은 고딕", Font.BOLD, 40);
		Font bt_bold = new Font("맑은 고딕", Font.BOLD, 30);
		
		//색깔 생성
		Color gray = new Color(204,204,204);
		Color white = new Color(255,255,255);
		Color light_blue = new Color(153,153,255);
		
		//p_all(전체적인 레이아웃) 설정
		this.add(p_all);
		p_all.setLayout(new FlowLayout());
	
		//p_cal 레이아웃
		p_cal.setLayout(new GridLayout(2,1));
		p_cal.setPreferredSize(new Dimension(290,80)); // 레이아웃 크기 설정
		process = new JLabel("",JLabel.RIGHT);
		result = new JLabel("0",JLabel.RIGHT);
		p_cal.add(process);
		p_cal.add(result);
		
		//p_cal 레이블 정렬
		process.setAlignmentX(RIGHT_ALIGNMENT);
		result.setAlignmentX(RIGHT_ALIGNMENT);
		
		//p_cal 폰트 적용
		result.setFont(bold);
		
		//p_cal 색상 적용
		process.setForeground(Color.gray);
		
		//p_cont 레이아웃
		p_cont.setLayout(new GridLayout(6,4));
		p_cont.setPreferredSize(new Dimension(290,300));
		
		//p_cont 1번줄
		rem = new JButton("%");
		rem.addActionListener(this); // 이벤트에 사용하기 위한 작업
		p_cont.add(rem); 
		ce = new JButton("CE");
		ce.addActionListener(this);
		p_cont.add(ce);
		c = new JButton("C");
		c.addActionListener(this);
		p_cont.add(c);
		b_space = new JButton("←");
		b_space.addActionListener(this);
		p_cont.add(b_space);
		
		//p_cont 2번줄
		frac = new JButton("¹/x");
		frac.addActionListener(this);
		p_cont.add(frac);
		squa = new JButton("x²");
		squa.addActionListener(this);
		p_cont.add(squa);
		root = new JButton("²√x");
		root.addActionListener(this);
		p_cont.add(root);
		div = new JButton("÷");
		div.addActionListener(this);
		p_cont.add(div);
		
		//p_cont 3번줄
		seven = new JButton("7");
		seven.addActionListener(this);
		p_cont.add(seven);
		eight = new JButton("8");
		eight.addActionListener(this);
		p_cont.add(eight);
		nine = new JButton("9");
		nine.addActionListener(this);
		p_cont.add(nine);
		mul = new JButton("×");
		mul.addActionListener(this);
		p_cont.add(mul);
		
		//p_cont 4번줄
		four = new JButton("4");
		four.addActionListener(this);
		p_cont.add(four);
		five = new JButton("5");
		five.addActionListener(this);
		p_cont.add(five);
		six = new JButton("6");
		six.addActionListener(this);
		p_cont.add(six);
		minus = new JButton("-");
		minus.addActionListener(this);
		p_cont.add(minus);
		
		//p_cont 5번줄
		one = new JButton("1");
		one.addActionListener(this);
		p_cont.add(one);
		two = new JButton("2");
		two.addActionListener(this);
		p_cont.add(two);
		three = new JButton("3");
		three.addActionListener(this);
		p_cont.add(three);
		plus = new JButton("+");
		plus.addActionListener(this);
		p_cont.add(plus);
				
		//p_cont 6번줄
		sign = new JButton("+/-");
		sign.addActionListener(this);
		p_cont.add(sign);
		zero = new JButton("0");
		zero.addActionListener(this);
		p_cont.add(zero);
		point = new JButton(".");
		point.addActionListener(this);
		p_cont.add(point);
		equal = new JButton("=");
		equal.addActionListener(this);
		p_cont.add(equal);
		
		//p_cont 폰트 사이즈 설정
		zero.setFont(bt_bold);
		one.setFont(bt_bold);
		two.setFont(bt_bold);
		three.setFont(bt_bold);
		four.setFont(bt_bold);
		five.setFont(bt_bold);
		six.setFont(bt_bold);
		seven.setFont(bt_bold);
		eight.setFont(bt_bold);
		nine.setFont(bt_bold);
		
		//p_cont 버튼 배경색 설정
		rem.setBackground(gray);
		ce.setBackground(gray);
		c.setBackground(gray);
		b_space.setBackground(gray);
		frac.setBackground(gray);
		squa.setBackground(gray);
		root.setBackground(gray);
		div.setBackground(gray);
		mul.setBackground(gray);
		minus.setBackground(gray);
		plus.setBackground(gray);
		sign.setBackground(gray);
		point.setBackground(gray);
		
		equal.setBackground(light_blue);
		
		zero.setBackground(white);
		one.setBackground(white);
		two.setBackground(white);
		three.setBackground(white);
		four.setBackground(white);
		five.setBackground(white);
		six.setBackground(white);
		seven.setBackground(white);
		eight.setBackground(white);
		nine.setBackground(white);
		
		//전체내용
		p_all.add(p_cal);
		p_all.add(p_cont);
		
		//창 보이기 설정(true : 보임 , false 안보임)
		setVisible(true);
	}
	
	public static void main(String[] args) {
		// Corine의 계산기 실행
		new Calculator("계산기");
	}
	
	// 마우스 클릭에 의한 동작
	public void actionPerformed(ActionEvent e) {
	
	// getActionCommand()는 action 명령을 나타내는 문자열을 제공
	// getSource()는 이벤트가 발생된 객체를 가져옴
		
		// 첫번째 피연산자에 값이 있고 두번째 피연산자와 연산자를 받지 않은 경우 처리
		if(num1 != null && num2 == null && func == null) {
			if (e.getSource() == one) {
				num1 = num1 + "1";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == two) {
				num1 = num1 + "2";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == three) {
				num1 = num1 + "3";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == four) {
				num1 = num1 + "4";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == five) {
				num1 = num1 + "5";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == six) {
				num1 = num1 + "6";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == seven) {
				num1 = num1 + "7";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == eight) {
				num1 = num1 + "8";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == nine) {
				num1 = num1 + "9";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == zero) {
				num1 = num1 + "0";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if(e.getSource() == plus) {
				func = "+";
				pro = pro + func;
				process.setText(pro);
			} else if (e.getSource() == minus){
				func = "-";
				pro = pro + func;
				process.setText(pro);
			} else if (e.getSource() == mul){
				func = "×";
				pro = pro + func;
				process.setText(pro);
			} else if (e.getSource() == div){
				func = "÷";
				pro = pro + func;
				process.setText(pro);
			} else if (e.getSource() == rem){
				func = "%";
				pro = pro + func;
				process.setText(pro);
			} else if (e.getSource() == frac){
				pro = "1/(" + num1 +  ")";
				result_num = Double.toString(1/Double.valueOf(num1));
				process.setText(pro);
				result.setText(result_num);
				num1 = result_num;
			} else if (e.getSource() == squa){
				pro = "sqr(" + num1 + ")";
				result_num = Double.toString(Double.valueOf(num1) * Double.valueOf(num1));
				process.setText(pro);
				result.setText(result_num);
				num1 = result_num;
			} else if (e.getSource() == root){
				pro = "√(" + num1 + ")";
				result_num = Double.toString(Math.sqrt(Double.valueOf(num1)));
				process.setText(pro);
				result.setText(result_num);
				num1 = result_num;
			} else if (e.getSource() == sign){
				result_num = Double.toString((-1) * (Double.valueOf(num1)));
				pro = result_num;
				process.setText(pro);
				result.setText(result_num);
				num1 = result_num;
			} else if (e.getSource() == point){
				result_num = "0.";
				pro = result_num;
				process.setText(pro);
				result.setText(result_num);
				num1 = result_num;
			}
			
		// 첫번째 피연산자, 두번째 피연산자와 연산자를 받지 않은 경우 처리	
		} else if(num1 == null && num2 == null && func == null){
			if (e.getSource() == one) {
				num1 = "1";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == two) {
				num1 = "2";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == three) {
				num1 = "3";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == four) {
				num1 = "4";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == five) {
				num1 = "5";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == six) {
				num1 = "6";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == seven) {
				num1 = "7";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == eight) {
				num1 = "8";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == nine) {
				num1 = "9";
				pro = num1;
				result_num = num1;
				process.setText(pro);
				result.setText(result_num);
			} else if (e.getSource() == zero) {
				num1 = "0";
				pro = num1;
				result_num = num1;
				process.setText("0");
				result.setText("0");
			}
		// 첫번째 피연산자, 연산자에 값이 있고 두번째 피연산자를 받지 않은 경우 처리	
		} else if(num1 != null && num2 == null && func != null) {
			if(e.getSource() == plus) {
				func = "+";
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == minus){
				func = "-";
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == mul){
				func = "×";
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == div){
				func = "÷";
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == rem){
				func = "%";
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == one) {
				num2 = "1";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == two) {
				num2 = "2";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == three) {
				num2 = "3";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == four) {
				num2 = "4";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == five) {
				num2 = "5";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == six) {
				num2 = "6";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == seven) {
				num2 = "7";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == eight) {
				num2 = "8";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == nine) {
				num2 = "9";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == zero) {
				num2 = "0";
				pro = pro + num2;
				process.setText(pro);
				result.setText(num2);
			}
			
		// 첫번째 피연산자, 두번째 피연산자, 연산자에 값이 있는 경우 처리	
		} else if(num1 != null && num2 != null && func != null) {
			if (e.getSource() == one) {
				num2 = num2 + "1";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == two) {
				num2 = num2 + "2";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == three) {
				num2 = num2 + "3";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == four) {
				num2 = num2 + "4";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == five) {
				num2 = num2 + "5";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == six) {
				num2 = num2 + "6";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == seven) {
				num2 = num2 + "7";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == eight) {
				num2 = num2 + "8";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == nine) {
				num2 = num2 + "9";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if (e.getSource() == zero) {
				num2 = num2 + "0";
				pro = pro + num2.substring(num2.length()-1);
				process.setText(pro);
				result.setText(num2);
			} else if(e.getSource() == plus) {
				func = "+";
				num2 = null;
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == minus){
				func = "-";
				num2 = null;
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == mul){
				func = "×";
				num2 = null;
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == div){
				func = "÷";
				num2 = null;
				pro = num1 + func;
				process.setText(pro);
			} else if (e.getSource() == rem){
				func = "%";
				num2 = null;
				pro = num1 + func;
				process.setText(pro);
			} else if(e.getSource() == equal) {
				if(func == "-")
					result_num = Double.toString(Double.valueOf(num1) - Double.valueOf(num2));
				else if(func == "×")
					result_num = Double.toString(Double.valueOf(num1) * Double.valueOf(num2));
				else if(func == "÷")
					result_num = Double.toString(Double.valueOf(num1) / Double.valueOf(num2));
				else if(func == "%")
					result_num = Double.toString(Double.valueOf(num1) % Double.valueOf(num2));
				else if(func == "+")
					result_num = Double.toString(Double.valueOf(num1) + Double.valueOf(num2));
				process.setText(result_num);
				result.setText(result_num);
				num1 = result_num;
			} 
		} 
		// c 버튼을 클릭한 경우 처리
		if(e.getSource() == c) {
			num1 = null;
			num2 = null;
			func = null;
			process.setText("");
			result.setText("");
		// ce 버튼을 클릭한 경우 처리
		} else if(e.getSource() == ce) {
			if(num1 != null && num2 == null) {
				process.setText("");
				result.setText("");
			} else if(num1 != null && num2 != null) {
				result.setText("");
				process.setText(num1 + func);
				num2 = null;
			} else if(num1 == null && num2 == null) {
				result.setText("");
				process.setText("");
				num1 = null;
				num2 = null;
			} 
		// <- 버튼을 누른 경우 처리
		} else if(e.getSource() == b_space) {
			if(num1!= null) {
				num1 = num1.substring(0,num1.length()-1);
				if(result_num.length() > 0)
					result.setText(result_num.substring(0,num1.length()));
			}
			
			if(num2 != null) {
				num2.substring(0,num2.length()-1);
				if(result_num.length() > 0)
					result.setText(result_num.substring(0,num1.length()));
			}
		}
		
	}

}
 

 

3) 실행 결과(예시)

<계산기 UI>

 

4) 결과 상태 및 추가 보완점

- UI 완성

- 숫자 및 연산, 기타 버튼들 모두 동작은 하나 모든 케이스에 대한 대응 못함.

(ex. 소수점의 경우 첫번째 피연산자 입력 시에만 적용)

- 기호 폰트 크기 키우기

- 키패드 벌려놓기(여백칸 없애기)

- 키패드 모양 다른 모양으로 해보기(ex. 원, 삼각형 등)

- 키패드 폰트 넣어보기

- 패드 클릭 시 소리 나오게 하기

- 키패드 배경색 그라데이션으로 하기

- 제작 정보 탭으로 만들어 보기

 

5) Review

- 이벤트용 클래스를 제외하고 계산 관련 클래스를 만들지 않고 조건문으로만 처리하려고 하니까 코드가 더 복잡해지기만 하고 제기능을 하지 못했다. 내 생각만큼 로직이 점점 복잡해지고 애초에 로직 생각을 잘 안했던 것이 드러났다. 기능 그나마 이벤트 동작 인터페이스 및 클래스는 Google를 뒤적거리며 찾아 쓴 것이다. 문제는  그 안 내용물을 어제 시간을 다 쓰면서 혼자 코딩한 덕분에 시간만 낭비하고 스스로 고쳐나간게 별로 없다. 이미 하루가 지나가고 너무 늦어서 여기까지 하고 내일은 다른 자료도 찾아보고 클래스를 이용해서 반복적인 거는 소거해 나가는 식으로 진행해야겠다.