실무 연습

java로 계산기 만들기

Daryl 2023. 2. 16. 20:04

초보에게 가장 좋은 공부는 실전.

java로 계산기, 메모장, 그림판 만들기에 차례대로 도전해보기로 함.

 

첫번째 프로젝트는 계산기 만들기.

https://code-review.tistory.com/84

 

[클론코딩] 자바로 계산기 구현하기

🔗YouTube / 동현 1-0 IMPORT 내용 알아보기 import java.awt.Color; 색을 표현하기 위한 클래스 원하는 색의 RGB값만 알고 있으면 객체를 생성하여 사용할 수 있다. 🔗 import java.awt.Font; 글자에 효과를 주기

code-review.tistory.com

위 글을 참고하여 구현하기로 함. 모르는 문법은 그때그때 공부하며 보완할 생각.

 

1. 모양 구현하기

 

● src 폴더는 소스코드 파일이 저장되는 곳. 클래스 등의 파일도 해당 폴더 내에서 생성해야 함.

● import문을 통해 컴파일러는 소스파일에 사용된 클래스들의 패키지를 알 수 있고,

모든 클래스 이름 앞에 패키지 명을 붙여 줌.

참고글에 나온대로 코드를 작성했음. 그 과정에서 A1 패키지 밑으로 Calculator 프로그램 넣음.

느낌표(warning)이 뜨지만 중요한건 아니므로 무시. 위 코드를 실행하면

위와 같이 '계산기'라고 적힌 빈 창이 생성됨. 모양 구현 성공.

 

1. 모양 구현하기 - 2 

 

창의 사이즈, 위치, 레이아웃을 지정하는 코드를 추가하여 수정.

package A1_materializeShape;

import java.awt.Color;
import java.awt.Font;

import javax.swing.JFrame;
import javax.swing.JTextField;

public class Calculator extends JFrame{
	
	private JTextField inputSpace;
	// inputSpace는 계산식이 들어가는 창을 의미함
	
	public Calculator() {
		
		//계산기의 화면과 버튼을 붙임 -> 기본 레이아웃 쓸 것임
		setLayout(null);
		
		//빈 공간의 JTextField 생성
		inputSpace = new JTextField();
		//편집가능여부: 불가능 (버튼만 사용)
		inputSpace.setEditable(false);
		//배경색 설정
		inputSpace.setBackground(Color.WHITE);
		//정렬 위치 설정
		inputSpace.setHorizontalAlignment(JTextField.RIGHT);
		//글씨체 설정
		inputSpace.setFont(new Font("Arial", Font.BOLD, 50));
		//위치와 크기(x:8, y=10의 위치에 270x70의 크기)
		inputSpace.setBounds(9, 10, 270, 70);
		
		add(inputSpace);
		
		//창의 제목, 사이즈, 보이기 여부 등을 지정
		setTitle("계산기");
		setVisible(true);
		setSize(300,370);
		//화면을 가운데에 띄움
		setLocationRelativeTo(null);
		//사이즈 조절 불가능
		setResizable(false);
		//창을 닫을 때 실행 중인 프로그램도 같이 종료되도록 함
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String[] args) {
			new Calculator();

	}

}

위 코드를 출력한 결과 ↓

 

2. 계산 기능 구현

 

계산기 버튼을 만들고, 각 버튼에 지정 값과 계산 기능을 추가할 것임.

그를 위해 ArrayList, Action메서드를 추가해야 함.

각 버튼의 배열과 그 배열값에 나타낼 문자를 지정하기 위함.

조건을 통해 버튼을 눌렀을 때의 반응을 지정할 수 있음.

 

●메서드method: 특정 작업을 수행하는 일련의 문장들을 하나로 묶은 것.

어떤 값을 입력하면 이 값으로 작업을 수행해서 결과를 반환함.

기본적으로 수학의 함수와 유사.

●메서드의 문법

반환 타입 메서드 이름 (타입 변수명, 타입 변수명, ...) 		>- 선언부
{   								│
		//메서드 호출 시 수행될 코드			│- 구현부
{   								│

● JTextField: 컨트롤 UI. 일명 텍스트 박스/ 인풋 박스. 

이것을 사용하면 빈 네모 칸이 나와서, 사용자가 그 안에 임의로 텍스트를 작성할 수 있음.

● setEditable(false): text area 수정 불가 설정 메소드. 

● setBackground(Color.bg): 배경색 바꾸는 메소드.

● setHorizontalAlignment: 수평 정렬 설정 메소드.

● setBounds(가로위치, 세로위치, 가로길이, 세로길이): 위치와 길이 설정 메소드. 

new GridLayout(행, 열, 가로여백, 세로여백): 테이블 모양을 만드는 메소드.

● setForeground(Color.fg): 글자색 바꾸는 메소드.

● addActionListener: 버튼이 눌렸을 때 동작하게 해주는 메소드.

● setVisible(true/false): 보이기 여부를 지정하는 메소드.

● setResizable(true/false): 사이즈 조절 여부를 정하는 메소드.

● setDefaultCloseOperation(EXIT_ON_CLOSE): 창을 닫을 때 프로그램도 종료되게 하는 메소드. 

● implements: 인터페이스 여러개 구현 가능.

● interface: 클래스들이 필수로 구현해야 하는 추상 자료형.

● extends: 클래스 확장. 클래스 하나만 상속 받을 수 있음.

→ implements, interface, extends 등의 부분에 있어서는 객체지향성의 이해가 중요해 보임.

자세히 공부하기엔 어려운 개념 같아서 간단히 학습해보겠음.

 

java의 객체지향Object Oriented 프로그래밍적 특징:

1. 클래스를 여러개 만드는 대신 하나의 클래스 내에서 여러 객체를 생성하여 동일한 일을 할 수 있어 효율적.

2. new 는 객체를 생성할 때 쓰는 키워드.

3. 클래스에서 만들어진 객체는 'a는 b클래스의 인스턴스instance'라고 표현.

4. 쉽게 비유하면 클래스는 과자틀, 객체는 과자.

5. 객체 변수Instance variable: 클래스에 선언된 변수. a.k.a. 인스턴스 변수, 멤버 변수, 속성.

6. 객체 변수의 문법 → 객체.객체변수

7. 객체 변수를 선언해도 아무런 값을 할당하지 않으면 출력 시 null이 나옴.

8. 메소드Method: 클래스 내에 구현된 함수.

9. 객체 변수는 공유되지 않음. 그래서 static을 이용해 공유함. 

10. 메소드에 객체reference type를 전달하면 객체의 객체변수(속성) 값을 바꿀 수 있음.

11. 상속inheritance 기능을 통해 자식 클래스가 모부 클래스의 기능을 그대로 물려받을 수 있음.

12. 클래스 상속을 위해 extends 키워드 사용.

13. java는 다중 상속을 지원하지 않음.

14. 인터페이스는 interface라는 키워드를 통해 작성.

15. 인터페이스는 implements라는 키워드를 통해 구현.

 

더 많은 내용이 있는데 아직까진 제대로 이해가 안감. 추후 다시 공부할 예정.

 

 

코드 수정↓

package A1_materializeShape;

import java.awt.Color;
import java.awt.Font;
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.JPanel;
import javax.swing.JTextField;

public class Calculator extends JFrame{
	// inputSpace는 계산식이 들어가는 창을 의미함
	private JTextField inputSpace;
	//계산식의 숫자를 담을 변수 num
	private String num = "";
	//계산 기능을 구현하기 위해 ArrayList에 숫자와 연관 기호를 하나씩 구분해 담음
	private ArrayList<String> equation = new ArrayList<String>();
	
	public Calculator() {
		//계산기의 화면과 버튼을 붙임 -> 기본 레이아웃 쓸 것임
		setLayout(null);
		
		//빈 공간의 JTextField 생성
		inputSpace = new JTextField();
		//편집가능여부: 불가능 (버튼만 사용)
		inputSpace.setEditable(false);
		//배경색 설정
		inputSpace.setBackground(Color.WHITE);
		//정렬 위치 설정
		inputSpace.setHorizontalAlignment(JTextField.RIGHT);
		//글씨체 설정
		inputSpace.setFont(new Font("Arial", Font.BOLD, 50));
		//위치와 크기(x:8, y=10의 위치에 270x70의 크기)
		inputSpace.setBounds(8, 10, 270, 70);
		
		//버튼을 만들 패널
		JPanel buttonPanel = new JPanel();
		//레이아웃 지정 - 격자형태로 배치해주는 GridLayout 사용
		//GridLayout(4, 4, 10, 10) -> 가로 칸수, 세로 칸수, 좌우 간격, 상하 간격
		buttonPanel.setLayout(new GridLayout(4, 4, 10, 10));
		//위치와 크기 설정
		buttonPanel.setBounds(8, 90, 270, 235);
		
		//계산기 버튼의 글자를 차례대로 배열에 저장
		String button_names[] = {"C", "÷", "×", "=", "7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "0" };
		//버튼들의 배열
		JButton buttons[] = new JButton[button_names.length];
		
		//배열을 이용하여 버튼 생성
		for (int i = 0; i < button_names.length; i++) {
				buttons[i] = new JButton(button_names[i]);
				//글씨체
				buttons[i].setFont(new Font("Arial", Font.BOLD, 20));
				//버튼 색 지정
				if (button_names[i] == "C") buttons[i].setBackground(Color.RED);
				else if ((i >= 4 && i <= 6) || (i >= 8 && i <= 10) || (i >= 12 && i <= 14)) buttons[i].setBackground(Color.BLACK);
				else buttons[i].setBackground(Color.GRAY);
				//글자색 지정
				buttons[i].setForeground(Color.WHITE);
				//테두리 없앰
				buttons[i].setBorderPainted(false);
				//밑에서 만든 액션리스너를 버튼에 추가
				buttons[i].addActionListener(new PadActionListener());
				//버튼들을 버튼패널에 추가
				buttonPanel.add(buttons[i]);
		}
		
		add(inputSpace);
		//버튼 패널 추가
		add(buttonPanel);
		
		//창의 제목, 사이즈, 보이기 여부 등을 지정
		setTitle("계산기");
		setVisible(true);
		setSize(300,370);
		//화면을 가운데에 띄움
		setLocationRelativeTo(null);
		//사이즈 조절 불가능
		setResizable(false);
		//창을 닫을 때 실행 중인 프로그램도 같이 종료되도록 함
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	//만들어놓은 버튼에 액션 리스너 기능 추가
	//액션리스너를 상속시켜주고 actionPerformed(ActionEvent e)메소드로 이벤트 처리
	class PadActionListener implements ActionListener{
			public void actionPerformed(ActionEvent e) {
				//어떤 버튼이 눌렸는지 알아냄
				String operation = e.getActionCommand();
			
				//C가 눌렸을 경우 위의 계산식 내용을 지워줌
				if (operation.equals("C")) {
						inputSpace.setText("");
				//=이 눌렸을 경우 위에 입력된 식을 계산하고 값이 나오도록 함
				} else if (operation.equals("=")) {
						//밑의 메서드들을 이용하여 계산. 계산식 화면에 값 띄워줌
						String result = Double.toString(calculate(inputSpace.getText()));
						inputSpace.setText("" + result);
						num = "";
				//나머지 버튼은 눌렀을 때 계산식에 추가됨
				} else {
						inputSpace.setText(inputSpace.getText() + e.getActionCommand());
				}
		}
	}
	
	private void fullTextParsing(String inputText) {
			equation.clear();
		
			//계산식의 글자를 하나하나 거쳐감
			for (int i = 0; i < inputText.length(); i++) {
					char ch = inputText.charAt(i);
			
					//연산기호가 나오면 ArrayList에 추가되고 초기화
					if (ch == '-' || ch == '+' || ch == '×' || ch == '÷') {
							//연산기호를 만났다 : 앞은 숫자라는 것을 의미
							//숫자를 ArrayList에 추가
							equation.add(num);
							//num 초기화
							num = "";
							//연산기호를 ArrayList에 추가
							equation.add(ch + "");
					} else {
							//나머지는 그냥 숫자 처리
							num = num + ch;
					}
			}
			//반복문 끝나고 남아있는 숫자값 추가
			equation.add(num);
	}
	
	//계산 기능
	public double calculate(String inputText) {
			fullTextParsing(inputText);
		
			//위의 메서드를 실행하면 ArrayList에 숫자와 연산 기호가 담김
			double prev = 0;
			double current = 0;
			//연산 기호에 대한 처리를 위한 변수
			String mode = "";
		
			//+일 경우 add, -일 경우 sub, ×일 경우 mul, /일 경우 div
			for (String s : equation) {
					if (s.equals("+")) {
							mode = "add";
					} else if (s.equals("-")) {
							mode = "sub";
					}
					else if (s.equals("×")) {
							mode = "mul";
					}
					else if (s.equals("÷")) {
							mode = "div";
					} else {
							//숫자일 경우 문자열을 double로 형변환
							current = Double.parseDouble(s);
					
							//mode값에 따라 처리, prev는 계속 계산값이 갱신됨
							if (mode.equals("add")) {
									prev += current;
							} else if (mode.equals("sub")) {
									prev -= current;
							}
							else if (mode.equals("mul")) {
									prev *= current;
							}
							else if (mode.equals("div")) {
									prev /= current;
							} else {
									prev = current;
							}
				}
		}
		//계산값 prev 반환
		return prev;
	}
	
	public static void main(String[] args) {
			new Calculator();

	}

}

위 코드를 출력한 결과 ↓

 

 

3. 예외 사항 처리

 

위 코드는 문제점이 있음.

1. 사용자가 정상적인 식을 입력하지 않았을 때(ex.4++-5) 정상처리 할 수 없음.

2. 첫번째 값에 음수를 입력할 수 없음.

 

이를 아래와 같이 수정할 것임.

1. 계산식이 비어 있지 않고 연산자가 중복되지 않은 경우 정상 처리 가능. 

2. 첫 값에 음수를 입력할 수 있음.

3. 결과 값이 소수점 6번째 자리에서 반올림 되게 수정.

 

● 문법 &&:  AND 연산자. 모든 조건이 true일 때만 true 반환. ||보다 우선순위 높음.

문법 ||: OR 연산자. &&보다 우선순위 낮음.

● 문법 &: &&와 같은 결과를 도출하지만, 앞 조건식이 false여도 뒤 조건식의 true or false를 판별함.

● equals: 객체의 참조변수를 받아서 주소값을 비교해 그 결과를 boolean 값으로 알려주는 메소드.

● public: 외부 클래스가 자유롭게 사용할 수 있도록 허가하는 접근 제한자

● private: 외부 클래스의 사용을 불허하는 접근 제한자

● static: 정적, 고정된 이라는 의미에 걸맞게 객체가 아닌 클래스에 소속된 고정 멤버를 만드는 키워드.

static 변수(정적 필드)와 static 메소드(정적 메소드)를 만들 수 있고, 이 둘을 합쳐 정적 멤버라고 부름.

static 키워드를 통해 생성된 정적 멤버들은 static 영역에 메모리가 할당되어 모든 객체가 공유할 수 있음.

 

수정한 코드 ↓

package A1_materializeShape;

import java.awt.Color;
import java.awt.Font;
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.JPanel;
import javax.swing.JTextField;

public class Calculator extends JFrame{
	// inputSpace는 계산식이 들어가는 창을 의미함
	private JTextField inputSpace;
	//계산식의 숫자를 담을 변수 num
	private String num = "";
	//방금 누른 버튼을 기억하는 변수 prev_operation
	private String prev_operation = "";
	//계산 기능을 구현하기 위해 ArrayList에 숫자와 연관 기호를 하나씩 구분해 담음
	private ArrayList<String> equation = new ArrayList<String>();
	
	public Calculator() {
		//계산기의 화면과 버튼을 붙임 -> 기본 레이아웃 쓸 것임
		setLayout(null);
		
		//빈 공간의 JTextField 생성
		inputSpace = new JTextField();
		//편집가능여부: 불가능 (버튼만 사용)
		inputSpace.setEditable(false);
		//배경색 설정
		inputSpace.setBackground(Color.WHITE);
		//정렬 위치 설정
		inputSpace.setHorizontalAlignment(JTextField.RIGHT);
		//글씨체 설정
		inputSpace.setFont(new Font("Arial", Font.BOLD, 50));
		//위치와 크기(x:8, y=10의 위치에 270x70의 크기)
		inputSpace.setBounds(8, 10, 270, 70);
		
		//버튼을 만들 패널
		JPanel buttonPanel = new JPanel();
		//레이아웃 지정 - 격자형태로 배치해주는 GridLayout 사용
		//GridLayout(4, 4, 10, 10) -> 가로 칸수, 세로 칸수, 좌우 간격, 상하 간격
		buttonPanel.setLayout(new GridLayout(4, 4, 10, 10));
		//위치와 크기 설정
		buttonPanel.setBounds(8, 90, 270, 235);
		
		//계산기 버튼의 글자를 차례대로 배열에 저장
		String button_names[] = {"C", "÷", "×", "=", "7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "0" };
		//버튼들의 배열
		JButton buttons[] = new JButton[button_names.length];
		
		//배열을 이용하여 버튼 생성
		for (int i = 0; i < button_names.length; i++) {
				buttons[i] = new JButton(button_names[i]);
				//글씨체
				buttons[i].setFont(new Font("Arial", Font.BOLD, 20));
				//버튼 색 지정
				if (button_names[i] == "C") buttons[i].setBackground(Color.RED);
				else if ((i >= 4 && i <= 6) || (i >= 8 && i <= 10) || (i >= 12 && i <= 14)) buttons[i].setBackground(Color.BLACK);
				else buttons[i].setBackground(Color.GRAY);
				//글자색 지정
				buttons[i].setForeground(Color.WHITE);
				//테두리 없앰
				buttons[i].setBorderPainted(false);
				//밑에서 만든 액션리스너를 버튼에 추가
				buttons[i].addActionListener(new PadActionListener());
				//버튼들을 버튼패널에 추가
				buttonPanel.add(buttons[i]);
		}
		
		add(inputSpace);
		//버튼 패널 추가
		add(buttonPanel);
		
		//창의 제목, 사이즈, 보이기 여부 등을 지정
		setTitle("계산기");
		setVisible(true);
		setSize(300,370);
		//화면을 가운데에 띄움
		setLocationRelativeTo(null);
		//사이즈 조절 불가능
		setResizable(false);
		//창을 닫을 때 실행 중인 프로그램도 같이 종료되도록 함
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	//만들어놓은 버튼에 액션 리스너 기능 추가
	//액션리스너를 상속시켜주고 actionPerformed(ActionEvent e)메소드로 이벤트 처리
	class PadActionListener implements ActionListener{
			public void actionPerformed(ActionEvent e) {
				//어떤 버튼이 눌렸는지 알아냄
				String operation = e.getActionCommand();
			
				//C가 눌렸을 경우 위의 계산식 내용을 지워줌
				if (operation.equals("C")) {
						inputSpace.setText("");
				//=이 눌렸을 경우 위에 입력된 식을 계산하고 값이 나오도록 함
				} else if (operation.equals("=")) {
						//밑의 메서드들을 이용하여 계산. 계산식 화면에 값 띄워줌
						String result = Double.toString(calculate(inputSpace.getText()));
						inputSpace.setText("" + result);
						num = "";
				//지금 누른 버튼이 연산자일 때의 조건
				} else if (operation.equals("+") || operation.equals("-") || operation.equals("×") || operation.equals("÷")) {
						//첫 값을 음수로 입력할 수 있음
						if (inputSpace.getText().equals("") && operation.equals("-")) {
								inputSpace.setText(inputSpace.getText() + e.getActionCommand());
						
						//이전에 누른 버튼이 연산자가 아니고 && 위의 계산식이 비어있지 않을 때의 조건문
						} else if (!inputSpace.getText().equals("") && !prev_operation.equals("+") && !prev_operation.equals("-") && !prev_operation.equals("×") && !prev_operation.equals("÷")) {
								inputSpace.setText(inputSpace.getText() + e.getActionCommand());
						}
				}
				//나머지 버튼은 눌렀을 때 계산식에 추가됨
				else {
						inputSpace.setText(inputSpace.getText() + e.getActionCommand());
				}
				//마지막으로 누른 버튼을 기억
				prev_operation = e.getActionCommand();
		}
	}
	
	private void fullTextParsing(String inputText) {
			equation.clear();
		
			//계산식의 글자를 하나하나 거쳐감
			for (int i = 0; i < inputText.length(); i++) {
					char ch = inputText.charAt(i);
			
					//연산기호가 나오면 ArrayList에 추가되고 초기화
					if (ch == '-' || ch == '+' || ch == '×' || ch == '÷') {
							//연산기호를 만났다 : 앞은 숫자라는 것을 의미
							//숫자를 ArrayList에 추가
							equation.add(num);
							//num 초기화
							num = "";
							//연산기호를 ArrayList에 추가
							equation.add(ch + "");
					} else {
							//나머지는 그냥 숫자 처리
							num = num + ch;
					}
			}
			//반복문 끝나고 남아있는 숫자값 추가
			equation.add(num);
			//연산자가 있을 때 num을 ArayList에 추가하는데, 처음에 -가 있으면 ""가 추가되어 에러 발생
			//즉 ""을 제거
			equation.remove("");
	}
	
	//계산 기능
	public double calculate(String inputText) {
			fullTextParsing(inputText);
		
			//위의 메서드를 실행하면 ArrayList에 숫자와 연산 기호가 담김
			double prev = 0;
			double current = 0;
			//연산 기호에 대한 처리를 위한 변수
			String mode = "";
		
			//+일 경우 add, -일 경우 sub, ×일 경우 mul, /일 경우 div
			for (String s : equation) {
					if (s.equals("+")) {
							mode = "add";
					} else if (s.equals("-")) {
							mode = "sub";
					}
					else if (s.equals("×")) {
							mode = "mul";
					}
					else if (s.equals("÷")) {
							mode = "div";
					} else {
							//숫자일 경우 문자열을 double로 형변환
							current = Double.parseDouble(s);
					
							//mode값에 따라 처리, prev는 계속 계산값이 갱신됨
							if (mode.equals("add")) {
									prev += current;
							} else if (mode.equals("sub")) {
									prev -= current;
							}
							else if (mode.equals("mul")) {
									prev *= current;
							}
							else if (mode.equals("div")) {
									prev /= current;
							} else {
									prev = current;
							}
				}
				//소수점 여섯번째 자리에서 반올림 (화면 표시 제한 때문)
				prev = Math.round(prev * 100000) / 100000.0;
		}
		//계산값 prev 반환
		return prev;
	}
	
	public static void main(String[] args) {
			new Calculator();

	}

}

출력 결과 ↓

첫번째 값으로 음수 입력 가능.

 

 

4. 연산자 우선순위 매기기

 

위 코드의 문제점은 사칙연산이 우선순위 없이 순서대로만 계산된다는 것임.

따라서 곱셈 연산자와 나눗셈 연산자를 우선 처리하도록 수정함.

 

수정한 코드↓

package A1_materializeShape;

import java.awt.Color;
import java.awt.Font;
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.JPanel;
import javax.swing.JTextField;

public class Calculator extends JFrame{
	// inputSpace는 계산식이 들어가는 창을 의미함
	private JTextField inputSpace;
	//계산식의 숫자를 담을 변수 num
	private String num = "";
	//방금 누른 버튼을 기억하는 변수 prev_operation
	private String prev_operation = "";
	//계산 기능을 구현하기 위해 ArrayList에 숫자와 연관 기호를 하나씩 구분해 담음
	private ArrayList<String> equation = new ArrayList<String>();
	
	public Calculator() {
		//계산기의 화면과 버튼을 붙임 -> 기본 레이아웃 쓸 것임
		setLayout(null);
		
		//빈 공간의 JTextField 생성
		inputSpace = new JTextField();
		//편집가능여부: 불가능 (버튼만 사용)
		inputSpace.setEditable(false);
		//배경색 설정
		inputSpace.setBackground(Color.WHITE);
		//정렬 위치 설정
		inputSpace.setHorizontalAlignment(JTextField.RIGHT);
		//글씨체 설정
		inputSpace.setFont(new Font("Arial", Font.BOLD, 50));
		//위치와 크기(x:8, y=10의 위치에 270x70의 크기)
		inputSpace.setBounds(8, 10, 270, 70);
		
		//버튼을 만들 패널
		JPanel buttonPanel = new JPanel();
		//레이아웃 지정 - 격자형태로 배치해주는 GridLayout 사용
		//GridLayout(4, 4, 10, 10) -> 가로 칸수, 세로 칸수, 좌우 간격, 상하 간격
		buttonPanel.setLayout(new GridLayout(4, 4, 10, 10));
		//위치와 크기 설정
		buttonPanel.setBounds(8, 90, 270, 235);
		
		//계산기 버튼의 글자를 차례대로 배열에 저장
		String button_names[] = {"C", "÷", "×", "=", "7", "8", "9", "+", "4", "5", "6", "-", "1", "2", "3", "0" };
		//버튼들의 배열
		JButton buttons[] = new JButton[button_names.length];
		
		//배열을 이용하여 버튼 생성
		for (int i = 0; i < button_names.length; i++) {
				buttons[i] = new JButton(button_names[i]);
				//글씨체
				buttons[i].setFont(new Font("Arial", Font.BOLD, 20));
				//버튼 색 지정
				if (button_names[i] == "C") buttons[i].setBackground(Color.RED);
				else if ((i >= 4 && i <= 6) || (i >= 8 && i <= 10) || (i >= 12 && i <= 14)) buttons[i].setBackground(Color.BLACK);
				else buttons[i].setBackground(Color.GRAY);
				//글자색 지정
				buttons[i].setForeground(Color.WHITE);
				//테두리 없앰
				buttons[i].setBorderPainted(false);
				//밑에서 만든 액션리스너를 버튼에 추가
				buttons[i].addActionListener(new PadActionListener());
				//버튼들을 버튼패널에 추가
				buttonPanel.add(buttons[i]);
		}
		
		add(inputSpace);
		//버튼 패널 추가
		add(buttonPanel);
		
		//창의 제목, 사이즈, 보이기 여부 등을 지정
		setTitle("계산기");
		setVisible(true);
		setSize(300,370);
		//화면을 가운데에 띄움
		setLocationRelativeTo(null);
		//사이즈 조절 불가능
		setResizable(false);
		//창을 닫을 때 실행 중인 프로그램도 같이 종료되도록 함
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	//만들어놓은 버튼에 액션 리스너 기능 추가
	//액션리스너를 상속시켜주고 actionPerformed(ActionEvent e)메소드로 이벤트 처리
	class PadActionListener implements ActionListener{
			public void actionPerformed(ActionEvent e) {
				//어떤 버튼이 눌렸는지 알아냄
				String operation = e.getActionCommand();
			
				//C가 눌렸을 경우 위의 계산식 내용을 지워줌
				if (operation.equals("C")) {
						inputSpace.setText("");
				//=이 눌렸을 경우 위에 입력된 식을 계산하고 값이 나오도록 함
				} else if (operation.equals("=")) {
						//밑의 메서드들을 이용하여 계산. 계산식 화면에 값 띄워줌
						String result = Double.toString(calculate(inputSpace.getText()));
						inputSpace.setText("" + result);
						num = "";
				//지금 누른 버튼이 연산자일 때의 조건
				} else if (operation.equals("+") || operation.equals("-") || operation.equals("×") || operation.equals("÷")) {
						//첫 값을 음수로 입력할 수 있음
						if (inputSpace.getText().equals("") && operation.equals("-")) {
								inputSpace.setText(inputSpace.getText() + e.getActionCommand());
						
						//이전에 누른 버튼이 연산자가 아니고 && 위의 계산식이 비어있지 않을 때의 조건문
						} else if (!inputSpace.getText().equals("") && !prev_operation.equals("+") && !prev_operation.equals("-") && !prev_operation.equals("×") && !prev_operation.equals("÷")) {
								inputSpace.setText(inputSpace.getText() + e.getActionCommand());
						}
				}
				//나머지 버튼은 눌렀을 때 계산식에 추가됨
				else {
						inputSpace.setText(inputSpace.getText() + e.getActionCommand());
				}
				//마지막으로 누른 버튼을 기억
				prev_operation = e.getActionCommand();
		}
	}
	
	private void fullTextParsing(String inputText) {
			equation.clear();
		
			//계산식의 글자를 하나하나 거쳐감
			for (int i = 0; i < inputText.length(); i++) {
					char ch = inputText.charAt(i);
			
					//연산기호가 나오면 ArrayList에 추가되고 초기화
					if (ch == '-' || ch == '+' || ch == '×' || ch == '÷') {
							//연산기호를 만났다 : 앞은 숫자라는 것을 의미
							//숫자를 ArrayList에 추가
							equation.add(num);
							//num 초기화
							num = "";
							//연산기호를 ArrayList에 추가
							equation.add(ch + "");
					} else {
							//나머지는 그냥 숫자 처리
							num = num + ch;
					}
			}
			//반복문 끝나고 남아있는 숫자값 추가
			equation.add(num);
			//연산자가 있을 때 num을 ArayList에 추가하는데, 처음에 -가 있으면 ""가 추가되어 에러 발생
			//즉 ""을 제거
			equation.remove("");
	}
	
	//계산 기능
	public double calculate(String inputText) {
			fullTextParsing(inputText);
		
			//위의 메서드를 실행하면 ArrayList에 숫자와 연산 기호가 담김
			double prev = 0;
			double current = 0;
			//연산 기호에 대한 처리를 위한 변수
			String mode = "";
		
			//연산자 우선 순위 적용
			for (int i = 0; i < equation.size(); i++) {
					String s = equation.get(i);
					
					//연산자가 있을 때마다 mode 값을 변경
					if (s.equals("+")) {
							mode = "add";
					} else if (s.equals("-")) {
							mode = "sub";
					} else if (s.equals("×")) {
							mode = "mul";
					} else if (s.equals("÷")) {
							mode = "div";
					} else {
							//전에 있던 연산자가 곱셈이나 나눗셈이고 현재 인덱스의 값이 숫자일 때 연산 진행
							if ((mode.equals("mul") || mode.equals("div")) && !s.equals("+") && !s.equals("-") && !s.equals("×") && !s.equals("÷")) {
									Double one = Double.parseDouble(equation.get(i - 2));
									Double two = Double.parseDouble(equation.get(i));
									Double result = 0.0;
									
									//mode에 따라서 계산
									if (mode.equals("mul")) {
											result = one * two;
									} else if (mode.equals("div")) {
											result = one / two;
									}
									//result 값을 ArrayList에 추가
									equation.add(i + 1, Double.toString(result));
									
									for (int j = 0; j < 3; j++) {
											equation.remove(i - 2);
									}
									
									//예를 들어 3+5x6에서 3+30이 됐으니 인덱스를 2만큼 되돌아감
									i -= 2; //결과값이 생긴 인덱스로 이동
									
								}
						}			
			}			//곱셉 나눗셈을 먼저 계산
			
			//+일 경우 add, -일 경우 sub
			for (String s : equation) {
					if (s.equals("+")) {
							mode = "add";
					} else if (s.equals("-")) {
							mode = "sub";
					
					//곱셈, 나눗셈 연산 삭제됨
					} else {
							//숫자일 경우 문자열을 double로 형변환
							current = Double.parseDouble(s);
					
							//mode값에 따라 처리, prev는 계속 계산값이 갱신됨
							if (mode.equals("add")) {
									prev += current;
							} else if (mode.equals("sub")) {
									prev -= current;
							} else {
									prev = current;
							}
				}
				//소수점 여섯번째 자리에서 반올림 (화면 표시 제한 때문)
				prev = Math.round(prev * 100000) / 100000.0;
		}
		//계산값 prev 반환
		return prev;
	}
	
	public static void main(String[] args) {
			new Calculator();

	}

}

출력 결과↓

완성!