이전에 포스팅한 MVC 2까지의 내용을 응용하여 계산기 프로그램을 구현하고, GUI개념을 Java에 적용하여 버튼식 계산기 프로그램을 구현하였다.
1. MVC 2 내용 응용 _ 계산기 구현
1) 설계
: 코딩 전 구현할 내용 정리 및 설계에 대한 내용 정리
- 전체 흐름 파악
- M -> int num1, String op(+,-), int num2, int res(결과값) 필요
- V -> 입력, 출력메서드 필요
- MVC로 분할 : 사용자 입력 저장에 대해 두가지의 풀이방법 존재
- 사용자 입력 멤버변수로 저장하기 : View에서 진행
- 사용자 입력 메서드(void)로 저장하기 : ModelVO생성 후 진행
2) View
package view;
import java.util.InputMismatchException;
import java.util.Scanner;
// 범위 외 입력 예외처리 목적
class MyException extends Exception{
MyException(String message){
super(message);
}
}
public class CalculatorView {
//멤버변수(사용자의 입력) & 스캐너
Scanner sc = new Scanner(System.in);
MyException myExcep = new MyException("입력을 다시 확인하세요");
String mainMsg = "1. 계산하기 \n2. 종료하기";
//사용자입력 저장할 변수
private int action;
private int num1;
private int num2;
private String op;
//게터세터
public int getAction() {
return action;
}
public void setAction(int action) {
this.action = action;
}
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
// 시작화면
public void StartView() {
System.out.println("===계산기===");
System.out.println(mainMsg);
System.out.println("===========");
while(true) {
try {
System.out.println(">>");
int action = sc.nextInt();
if(action<1 || action>2) {
throw myExcep;
}
this.action = action;
break;
}catch(InputMismatchException e) {
sc.nextLine();
System.out.println("*정수로 입력하세요*");
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
}
// 정수1 입력
public int num1() {
while(true) {
try {
System.out.println("첫번째 정수 : ");
int num1 = sc.nextInt();
this.num1 = num1;
break;
}catch(InputMismatchException e) {
sc.nextLine();
System.out.println("*정수로 입력하세요*");
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
return num1;
}
// 정수2 입력
public int num2() {
while(true) {
try {
System.out.println("두번째 정수 : ");
int num2 = sc.nextInt();
this.num2 = num2;
break;
}catch(InputMismatchException e) {
sc.nextLine();
System.out.println("*정수로 입력하세요*");
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
return num2;
}
// 연산자입력
public String op() {
while(true) {
try {
System.out.println("연산자 : ");
String op = sc.next();
if(op.equals("+") || op.equals("-")) {
this.op = op;
break;
}
if(op.equals("*") || op.equals("/")) {
this.op = op;
break;
}
throw myExcep;
}catch(InputMismatchException e) {
sc.nextInt();
System.out.println("*연산자를 입력하세요*");
}catch(Exception e) {
System.out.println(e.getMessage());
}
}
return op;
}
// 출력메서드
public void print(Object obj) {
for(int i=0; i<5; i++) {
System.out.print("두구");
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println();
System.out.println(obj);
}
public void endPrint() {
System.out.println("★계산기를 종료합니다★");
}
}
사용자의 입력을 멤버변수에 저장하는 방식으로 진행
3) Model
package model;
public class CalculatorModel {
//멤버변수
private int num1;
private int num2;
private String op;
private int res;
//getter&setter
public int getNum1() {
return num1;
}
public void setNum1(int num1) {
this.num1 = num1;
}
public int getNum2() {
return num2;
}
public void setNum2(int num2) {
this.num2 = num2;
}
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
public int getRes() {
return res;
}
public void setRes(int res) {
this.res = res;
}
//계산메서드
public int res(Object obj) {
if (obj.equals("+")){//덧셈
this.res = num1 + num2;
} else if (obj.equals("-")){//뺄셈
this.res = num1 - num2;
} else if (obj.equals("*")) {//곱셈
this.res = num1 * num2;
} else if (obj.equals("/")) {//나눗셈
this.res = num1 / num2;
}
return res;
}
}
*기본생성자를 이용하여 작업 진행*
이때 생성자가 없을 경우, 멤버변수 초기화가 안되는 것을 유의할 것. 즉, setter를 호출해야한다.
4) Controller
package controller;
import model.CalculatorModel;
import view.CalculatorView;
public class CalculatorCtrl {
//접근선언
CalculatorModel model;
CalculatorView view;
//ctrl실행 메서드 : model과 view정보 불러오기
public void ctrlStart () {
model = new CalculatorModel();
view = new CalculatorView();
}
// 앱실행 메서드
public void appStart () {
while(true) {
view.StartView(); //main화면출력
//메인에서 1 입력시 계산실행
if(view.getAction()==1) {
//view의 입력 -> model에 저장
model.setNum1(view.num1());
model.setOp(view.op());
model.setNum2(view.num2());
// syso(num1 + num2 = res); 과 같다
view.print(model.getNum1()+model.getOp()+model.getNum2()
+"="+model.res(model.getOp()));
//메인에서 2 입력시 종료
}else if(view.getAction()==2) {
//종료문구 출력
view.endPrint();
break;
}
}
}
}
5) 실행결과
package class01;
import controller.CalculatorCtrl;
public class Client {
public static void main(String[] args) {
CalculatorCtrl ctrl = new CalculatorCtrl();
//데이터불러오기
ctrl.ctrlStart();
//앱실행
ctrl.appStart();
}
}
[출력화면 : ★ -> 입력]
===계산기===
1. 계산하기
2. 종료하기
===========
>>
1
첫번째 정수 :
8
연산자 :
*
두번째 정수 :
9
두구두구두구두구두구
8*9=72
===계산기===
1. 계산하기
2. 종료하기
===========
>>
종료
*정수로 입력하세요*
>>
2
★계산기를 종료합니다★
2. GUI 자바응용_ 버튼식 계산기 구현
1) 배경이론
UI / UX
UI (User Interface) : "사용자를 마주하다"라는 의미로, 사용자가 앱 사용시 마주하는 디자인, 레이아웃, 기술적인 부분을 말한다. 상세하게는 줄간격, 폰트, 색상, 반응성, 입출력단계, 애니메이션 효과 등 여러 부분을 포함한다.
UX (User Experience) : "사용자의 경험을 녹이다"라는 의미로, 앱을 주로 사용하는 사용자들의 경험(가장 먼저 터치하는 화면, 사용자의 선택 플로우 등)들을 분석하여 그것을 더 편하고 효율적인 방향으로 프로세스가 진행될 수 있도록 하는 과정 및 결과를 뜻한다. UI에서 파생되었다고 보아도 무관하다.
UI / UX에서는 사용자가 서비스를 이용하는 흐름을 잘 이해하는 것이 중요하다.
즉, 사용자 편의성을 항상 고려해야한다.
참고 : https://brunch.co.kr/@aw2sum/36
UI / UX 의 차이는?
아무리 보아도 혼란해... | UI / UX 이 두 가지의 차이에 대해서 잘 모르는 사람들이 많다. 솔직히 나도 이 두가지의 개념 구분은 최근에야 하였고, 그 내용을 정리하고자 브런치에 남기려고 한다.
brunch.co.kr
GUI (Graphical User Interface)
직역하면 "그래픽 사용자 인터페이스"이다.
사용자 편의성을 고려하여 입출력 등의 기능을 알기 쉬운 아이콘, 버튼 등의 그래픽으로 나타낸 것이다.
GUI란? (graphical user interface, GUI) 구이☆★
줴유ㅇㅏ이인데 자꾸 구이라고 하게 된다☆★ GUI (Graphical User Interface, 그래픽 사용자 인터페...
blog.naver.com
컴포넌트
제품의 모듈과 유사한 개념으로, 소프트웨어상의 모듈이라고 할 수 있다.
독립적인 기능을 수행하도록 구현하여, 이를 다른 부분에 응용 or 삽입하여 사용할 수 있도록 한다.(핸드폰 탈부착 배터리의 기능과 유사!) 컴포넌트는 소프트웨어의 재사용의 중요성과 필용성을 위해 나온 기술이며, 이로인해 개발시간 단축, 개발비용 절감의 이점을 이행할 수 있다. 추가로 입력을 강제할 수 있다는 특징이 있다.
(ex. 전화번호 입력시 [ ][ ][ ]or[ - - ]따위로 입력을 구체적으로 정의)
참고 : https://mommoo.tistory.com/55
컴포넌트(Component)란?
컴포넌트(Component)개념의 등장배경 과 의미에 대해 기술한다. 컴포넌트 개념의 유래 많은 하드웨어 제품들은 각각 독립된 기능을 가진 모듈로 만들어진다. 이 제품들은 회사 상관없이 서로 조합
mommoo.tistory.com
2) View
package view;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
// 상속을 통해 Frame으로 만듦!
public class CalcView2 extends JFrame{
public JTextField n1, n2;
public JComboBox<String> op;
public JButton btn;
public JLabel res;
//위의 요소들을 여기에 붙인다.
JPanel panel;
// *생성자 내부에서 멤버변수 초기화 진행*
public CalcView2() {
setTitle("계산기 MVC 실습");
n1 = new JTextField(5); //생성자 내부의 칸 크기 설정
n2 = new JTextField(5); //생성자 내부의 칸 크기 설정
op = new JComboBox(); //스크롤박스
// 스크롤박스 내부의 문자표시
op.addItem("+");
op.addItem("-");
op.addItem("/");
op.addItem("x"); //*의 표시
btn = new JButton("계산하기"); //버튼글씨
res = new JLabel(); //버튼
// 모든 GUI View는 레이아웃을 설정한다.
setLayout(new FlowLayout()); //그리드 같은 것
panel = new JPanel();
panel.add(n1);
panel.add(op);
panel.add(n2);
panel.add(btn);
add(panel);
add(res);
setVisible(true); //화면에 안뜨는게 기본
//창의 X버튼을 눌렀을때, 종료되도록한다. -> 미선언시 X눌러도 미종료
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// 리셋
public void reset() {
n1.setText(""); //공백없이 진행
n2.setText(""); //공백없이 진행
}
}
: 별도의 필기 없이 필드의 주석을 통해 내용 파악이 가능하다.
3) Model
package model;
public class CalcModel2 {
//멤버변수
private int n1, n2, res;
private String op;
//생성자
public CalcModel2(int n1, int n2, String op) {
super();
this.n1 = n1;
this.n2 = n2;
this.op = op;
//model생성자에 인자가 들어오면
//계산메서드 진행을 통해 res값 setting!
calculate();
}
// 메서드에 값변경에 대한 로직이 들어있는 경우.
// 즉, 멤버변수의 값을 초기화하는 로직은 private을 통해 감출 수 있다.
// but, 로직코드는 공개하기
private void calculate() {
if (op.equals("+")){
this.res = plus(n1, n2);
} else if (op.equals("-")){
this.res = minus(n1, n2);
} else if (op.equals("/")){
this.res = divide(n1, n2);
} else if (op.equals("x")){
this.res = multip(n1, n2);
}
}
// 순수 알고리즘 코드! == 컴포넌트
// 이러한 로직코드는 재사용을 위해 open하는 것이 좋다!
public int plus(int n1, int n2) {
return n1 + n2;
}
public int minus(int n1, int n2) {
return n1 - n2;
}
public int divide(int n1, int n2) {
return n1 / n2;
}
public int multip(int n1, int n2) {
return n1 * n2;
}
//결과 출력하는 메서드
public String printRes() {
return n1 + " " + op + " " + n2 + "=" + res;
}
// getter & setter
public int getN1() {
return n1;
}
public void setN1(int n1) {
this.n1 = n1;
}
public int getN2() {
return n2;
}
public void setN2(int n2) {
this.n2 = n2;
}
public int getRes() {
return res;
}
public void setRes(int res) {
this.res = res;
}
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
}
: 별도의 필기 없이 필드의 주석을 통해 내용 파악이 가능하다.
4) Controller
package controller;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import model.CalcModel2;
import view.CalcView2;
// FrameView인 경우 버튼에 대한 반응 구현 필수
// 인터페이스를 통해 강제 할 수 있다.
// * 하단 필기내용 참고 *
public class CalcCtrl2 implements ActionListener{ //Listener : 모니터링(감지체크)
CalcView2 view;
public CalcCtrl2 () {
view = new CalcView2();
//뷰에 현재 구현한 Ctrl를 더하는(연결) 작업
view.btn.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
// e = 액션 그 차제 : 버튼을 누른 행위
if(e.getSource()==view.btn) { // if,버튼을 눌렀다면
//사용자의 정보의 저장은 String으로 진행됨
String n1 = view.n1.getText();
String n2 = view.n2.getText();
String op = view.op.getSelectedItem().toString();
// 유효성체크
if(!n1.matches("[0-9]+") || !n2.matches("[\\d]+")) {
//정규식
view.res.setText("정수만 입력하세요");
view.reset();
return;
} else if (op.equals("/") && n2.equals("0")) {
view.res.setText("불능");
view.reset();
return;
}
CalcModel2 calc = new CalcModel2(Integer.parseInt(n1), Integer.parseInt(n2), op);
String res = calc.printRes();
view.res.setText(res);
view.reset();
}
}
}
* 필기 : ActionListener *
ActionListener이라는 interface 안에 actionPerformed를 @Override해서 해당 메소드안에 실행코드를 입력하게 되면, 지정한 Component의 액션이 발생했을 때, 실행코드가 작동하게 된다.
5) 실행결과
: 컨트롤러의 초기화만으로 출력 가능
package class01;
import controller.CalcCtrl2;
public class Client2 {
public static void main(String[] args) {
new CalcCtrl2();
}
}
- 실행 가능한 메서드
콘솔이 빨강색으로 실행중임을 알 수 있다. - 정상입력시
정상입력시의 출력화면 - 비정상입력시
'JAVA' 카테고리의 다른 글
[MVC] 학생관리시스템 : 예제 (0) | 2022.01.17 |
---|---|
[컬렉션 프레임워크] 학생관리시스템_배열리스트 (0) | 2022.01.15 |
[MVC] MVC개념 & DAO·VO (0) | 2022.01.15 |
[파일 입출력] TXT & 이미지형식 (+Wrapper Class) (0) | 2022.01.14 |
[Thread] 블록 & 동기화 (0) | 2022.01.13 |