-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpycalc.py
More file actions
124 lines (99 loc) · 3.5 KB
/
pycalc.py
File metadata and controls
124 lines (99 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""PyCalc is a simple calculator built with Python and PyQt."""
import sys
from functools import partial
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import (
QApplication,
QGridLayout,
QLineEdit,
QMainWindow,
QPushButton,
QVBoxLayout,
QWidget,
)
ERROR_MSG = "ERROR"
WINDOW_SIZE = 235
DISPLAY_HEIGHT = 35
BUTTON_SIZE = 40
class PyCalcWindow(QMainWindow):
"""PyCalc's main window (GUI or view)."""
def __init__(self):
super().__init__()
self.setWindowTitle("PyCalc")
self.setFixedSize(WINDOW_SIZE, WINDOW_SIZE)
self.generalLayout = QVBoxLayout()
centralWidget = QWidget(self)
centralWidget.setLayout(self.generalLayout)
self.setCentralWidget(centralWidget)
self._createDisplay()
self._createButtons()
def _createDisplay(self):
self.display = QLineEdit()
self.display.setFixedHeight(DISPLAY_HEIGHT)
self.display.setAlignment(Qt.AlignmentFlag.AlignRight)
self.display.setReadOnly(True)
self.generalLayout.addWidget(self.display)
def _createButtons(self):
self.buttonMap = {}
buttonsLayout = QGridLayout()
keyBoard = [
["7", "8", "9", "/", "C"],
["4", "5", "6", "*", "("],
["1", "2", "3", "-", ")"],
["0", "00", ".", "+", "="],
]
for row, keys in enumerate(keyBoard):
for col, key in enumerate(keys):
self.buttonMap[key] = QPushButton(key)
self.buttonMap[key].setFixedSize(BUTTON_SIZE, BUTTON_SIZE)
buttonsLayout.addWidget(self.buttonMap[key], row, col)
self.generalLayout.addLayout(buttonsLayout)
def setDisplayText(self, text):
"""Set the display's text."""
self.display.setText(text)
self.display.setFocus()
def displayText(self):
"""Get the display's text."""
return self.display.text()
def clearDisplay(self):
"""Clear the display."""
self.setDisplayText("")
def evaluateExpression(expression):
"""Evaluate an expression (Model)."""
try:
result = str(eval(expression, {}, {}))
except Exception:
result = ERROR_MSG
return result
class PyCalc:
"""PyCalc's controller class."""
def __init__(self, model, view):
self._evaluate = model
self._view = view
self._connectSignalsAndSlots()
def _calculateResult(self):
result = self._evaluate(expression=self._view.displayText())
self._view.setDisplayText(result)
def _buildExpression(self, subExpression):
if self._view.displayText() == ERROR_MSG:
self._view.clearDisplay()
expression = self._view.displayText() + subExpression
self._view.setDisplayText(expression)
def _connectSignalsAndSlots(self):
for keySymbol, button in self._view.buttonMap.items():
if keySymbol not in {"=", "C"}:
button.clicked.connect(
partial(self._buildExpression, keySymbol)
)
self._view.buttonMap["="].clicked.connect(self._calculateResult)
self._view.display.returnPressed.connect(self._calculateResult)
self._view.buttonMap["C"].clicked.connect(self._view.clearDisplay)
def main():
"""PyCalc's main function."""
pycalcApp = QApplication([])
pycalcWindow = PyCalcWindow()
pycalcWindow.show()
PyCalc(model=evaluateExpression, view=pycalcWindow)
sys.exit(pycalcApp.exec())
if __name__ == "__main__":
main()