🎆

004 생선가게 POS기 만들기 - 2

1. 기획

위에서 만들어본 간단한 계산기를 가지고 실제 사용할 수 있는 수준의 계산기를 한 번 만들어 보도록 하겠습니다.

2. 코드

from PyQt5.QtCore import Qt import sys from PyQt5.QtWidgets import * class 생선가게POS기(QWidget): def __init__(self): super().__init__() self.UI초기화() def UI초기화(self): self.s = '' ## number ## self.one = QPushButton('1') self.one.clicked.connect(lambda:self.clickedNum('1')) self.two = QPushButton('2') self.two.clicked.connect(lambda:self.clickedNum('2')) self.three = QPushButton('3') self.three.clicked.connect(lambda:self.clickedNum('3')) self.four = QPushButton('4') self.four.clicked.connect(lambda:self.clickedNum('4')) self.five = QPushButton('5') self.five.clicked.connect(lambda:self.clickedNum('5')) self.six = QPushButton('6') self.six.clicked.connect(lambda:self.clickedNum('6')) self.seven = QPushButton('7') self.seven.clicked.connect(lambda:self.clickedNum('7')) self.eight = QPushButton('8') self.eight.clicked.connect(lambda:self.clickedNum('8')) self.nine = QPushButton('9') self.nine.clicked.connect(lambda:self.clickedNum('9')) self.zero = QPushButton('0') self.zero.clicked.connect(lambda:self.clickedNum('0')) ## calculator ## self.plus = QPushButton('+') self.plus.clicked.connect(lambda:self.clickedNum('+')) self.minus = QPushButton('-') self.minus.clicked.connect(lambda:self.clickedNum('-')) self.division = QPushButton('/') self.division.clicked.connect(lambda:self.clickedNum('/')) self.multiply = QPushButton('*') self.multiply.clicked.connect(lambda:self.clickedNum('*')) self.dot = QPushButton('.') self.dot.clicked.connect(lambda:self.clickedNum('.')) self.squared = QPushButton('x^2') self.squared.clicked.connect(lambda:self.clickedNum('**2')) self.remainder = QPushButton('%') self.remainder.clicked.connect(lambda:self.clickedNum('%')) self.clear = QPushButton('Clear') self.clear.clicked.connect(self.clearText) self.back = QPushButton('Back') self.back.clicked.connect(self.backText) self.enter = QPushButton("=") self.enter.clicked.connect(self.calculateResult) self.lcd = QLineEdit('') self.lcd.setReadOnly(True) self.lcd.setAlignment(Qt.AlignRight) self.lcd.setStyleSheet('font-size:15px;font-weight:bold;padding:10px;') self.label = QLabel('계산기') grid = QGridLayout() grid.setSizeConstraint(QLayout.SetFixedSize) grid.addWidget(self.label, 0, 0, 1, 4, alignment=Qt.AlignCenter) grid.addWidget(self.lcd, 1, 0, 1, 4) grid.addWidget(self.plus, 2, 0) grid.addWidget(self.minus, 2, 1) grid.addWidget(self.multiply, 2, 2) grid.addWidget(self.division, 2, 3) grid.addWidget(self.seven, 3, 0) grid.addWidget(self.eight, 3, 1) grid.addWidget(self.nine, 3, 2) grid.addWidget(self.clear, 3, 3) grid.addWidget(self.four, 4, 0) grid.addWidget(self.five, 4, 1) grid.addWidget(self.six, 4, 2) grid.addWidget(self.back, 4, 3) grid.addWidget(self.one, 5, 0) grid.addWidget(self.two, 5, 1) grid.addWidget(self.three, 5, 2) grid.addWidget(self.squared, 5, 3) grid.addWidget(self.remainder, 6, 0) grid.addWidget(self.zero, 6, 1) grid.addWidget(self.dot, 6, 2) grid.addWidget(self.enter, 6, 3) self.setLayout(grid) self.setWindowTitle("계산기") self.show() def clickedNum(self, text): self.s += text self.lcd.setText(self.s) def calculateResult(self): self.lcd.setText(str(eval(self.s))) self.s = '' def clearText(self): self.lcd.setText('') self.s = '' def backText(self): self.s = self.s[:-1] self.lcd.setText(self.s) def keyPressEvent(self, event): if event.key() == Qt.Key_Return: self.calculateResult() elif event.key() == Qt.Key_Backspace: self.backText() elif event.key() == Qt.Key_Escape: self.close() 프로그램무한반복 = QApplication(sys.argv) 실행인스턴스 = 생선가게POS기() 프로그램무한반복.exec_()

3. 상세 내용

3.1 버튼,기호 표시 및 이벤트 연결

self.one = QPushButton('1') self.one.clicked.connect(lambda:self.clickedNum('1')) self.two = QPushButton('2') self.two.clicked.connect(lambda:self.clickedNum('2')) # ... 중략 ... self.nine = QPushButton('9') self.nine.clicked.connect(lambda:self.clickedNum('9')) self.zero = QPushButton('0') self.zero.clicked.connect(lambda:self.clickedNum('0'))
  • 0~9까지의 숫자 버튼을 추가하는 과정입니다. 여기서 lambda를 사용하는 이유는 connect( ) 안에 들어갔던 함수는 파라미터를 줄 경우 동작하지 않기 때문입니다. 즉, "( )" 가 없어야 실행됩니다.
 
self.plus = QPushButton('+') self.plus.clicked.connect(lambda:self.clickedNum('+')) self.minus = QPushButton('-') self.minus.clicked.connect(lambda:self.clickedNum('-')) # ... 중략 ... self.squared = QPushButton('x^2') self.squared.clicked.connect(lambda:self.clickedNum('**2')) self.remainder = QPushButton('%') self.remainder.clicked.connect(lambda:self.clickedNum('%'))
  • 계산 버튼들을 추가하는 과정입니다.
 
self.clear = QPushButton('Clear') self.clear.clicked.connect(self.clearText) self.back = QPushButton('Back') self.back.clicked.connect(self.backText) self.enter = QPushButton("=") self.enter.clicked.connect(self.calculateResult)
  • 그 외에 동작하는 이벤트를 지정해줍니다. 차례 대로 전체 텍스트 지우기, 하나의 텍스트 지우기, 계산을 수행하는 역활을 수행하게 됩니다.
 
self.lcd = QLineEdit("") self.lcd.setReadOnly(True) self.lcd.setAlignment(Qt.AlignRight) self.lcd.setStyleSheet("font-size:15pt;font-weight:bold;padding:10px;") self.label = QLabel("계산기") grid = QGridLayout() grid.setSizeConstraint(QLayout.SetFixedSize)
  • QLineEdit를 이용해 숫자및 기호들을 표시합니다.
  • setReadOnly(값): 읽기전용으로 동작합니다. 즉, QLineEdit에서 수정 불가
  • QGridLayout를 활용해 행과 열로 버튼들을 구성합니다.
 

3.2 함수(슬롯) 구현

def clickedNum(self, text): self.s += text self.lcd.setText(self.s)
def calculateResult(self): self.lcd.setText(str(eval(self.s))) self.s = ''
  • Enter 즉, 계산처리를 하는 함수
  • eval("문자열") 문자열에 따른 계산을 해주는 내장함수(Biltin-functions)
  • 코드를 조금 더 업데이트 한다면 try를 통해 먼저 이벤트 처리를 시도하고 에러가 나면 except문에서 처리할 수 있습니다.
def clearText(self): self.lcd.setText('') self.s = '' def backText(self): self.s = self.s[:-1] self.lcd.setText(self.s)
  • clear()를통해 사용자가 clear버튼을 누르면 QLineEdit값을 초기화
  • 사용자가 back버튼을 클릭하면 문자열 슬라이싱을 통해 QLineEdit에 값을 업데이트
 
def keyPressEvent(self, event): if event.key() == Qt.Key_Return: self.CalculateResult() elif event.key() == Qt.Key_Backspace: self.backText() elif event.key() == Qt.Key_Escape: self.close()
  • 마우스 이벤트를 추가하여 enter, backspace, ESC에 따른 이벤트 처리를 위해 선언했던 함수(슬롯)과 연결

4. 실행 결과

 
 
notion imagenotion image
 
notion imagenotion image
notion imagenotion image
 
 
notion imagenotion image
notion imagenotion image
 
notion imagenotion image
notion imagenotion image
 
notion imagenotion image
notion imagenotion image