-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
170 lines (140 loc) · 5.1 KB
/
main.py
File metadata and controls
170 lines (140 loc) · 5.1 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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
import tkinter as tk
from functools import partial
from tkinter import ttk
from module_loader import names
from secure_eval import eval_expr
# NOTE: LSP code rules:
# - ty LSP can perform type checking if you use hinting.
# Always use hinting on variables.
# For completions sake, use `typing.Any` if you ever need not to have
# strict typing.
# - Ruff LSP doesn't support star imports. Don't use star imports.
# INFO: Curricular competencies met:
# - Nothing yet!
# ------- Functions
# ----- Event functions
# Enters a string into the expression box; used for buttons.
def enterText(char: str) -> None:
print(f"Pressed '{char}' button.")
oldExpression: str = expression.get()
expression.set(oldExpression + char)
# Calculates the result and packs it into the output label.
def calculate() -> None:
expression_str: str = expression.get()
print(f"Calculating '{expression_str}'")
try:
result: str = eval_expr(expression_str, module_loader.names)
output.set(result)
print(f"Answer is '{result}'.")
except ValueError as e:
# Show error in GUI
output.set(f"ERROR: {e}")
# Show error in console
print(f"Caught an error: {e}")
# ------- Initialization
# ----- Initialize Tk and window
# Initialize Tk instance and window
root: tk.Tk = tk.Tk()
root.title("Calculator")
# Initialize themed frame
main_frame: ttk.Frame = ttk.Frame(root, padding=(12, 12, 12, 12))
main_frame.grid(sticky="nsew")
# Ensure main_frame expands to window size
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
# ----- Define layout and widgets
# --- Expression view/entry
expression: tk.StringVar = tk.StringVar()
expression_entry: ttk.Entry = ttk.Entry(main_frame, textvariable=expression)
expression_entry.grid(sticky="new")
# --- Output pane
output: tk.StringVar = tk.StringVar(value="= ?")
output_label: ttk.Label = ttk.Label(
main_frame, anchor="e", textvariable=output
)
output_label.grid(row=1, sticky="ew")
# --- Buttons panes
# Create buttons notebook (creates tabs for switching between button sets)
buttons_notebook: ttk.Notebook = ttk.Notebook(main_frame)
buttons_notebook.grid(row=2, sticky="nsew")
# Let buttons notebook take additional space
main_frame.rowconfigure(2, weight=1)
main_frame.columnconfigure(0, weight=1)
# Add arithmetic buttons frame
arithmetic_frame: ttk.Frame = ttk.Frame()
buttons_notebook.add(arithmetic_frame, text="Common")
# --- Buttons
# -- Arithmetic frame
# - Buttons definitions
button_1: ttk.Button = ttk.Button(
arithmetic_frame, text="1", command=partial(enterText, "1")
)
button_2: ttk.Button = ttk.Button(
arithmetic_frame, text="2", command=partial(enterText, "2")
)
button_3: ttk.Button = ttk.Button(
arithmetic_frame, text="3", command=partial(enterText, "3")
)
button_4: ttk.Button = ttk.Button(
arithmetic_frame, text="4", command=partial(enterText, "4")
)
button_5: ttk.Button = ttk.Button(
arithmetic_frame, text="5", command=partial(enterText, "5")
)
button_6: ttk.Button = ttk.Button(
arithmetic_frame, text="6", command=partial(enterText, "6")
)
button_7: ttk.Button = ttk.Button(
arithmetic_frame, text="7", command=partial(enterText, "7")
)
button_8: ttk.Button = ttk.Button(
arithmetic_frame, text="8", command=partial(enterText, "8")
)
button_9: ttk.Button = ttk.Button(
arithmetic_frame, text="9", command=partial(enterText, "9")
)
button_0: ttk.Button = ttk.Button(
arithmetic_frame, text="0", command=partial(enterText, "0")
)
button_decimal: ttk.Button = ttk.Button(
arithmetic_frame, text=".", command=partial(enterText, ".")
)
button_divide: ttk.Button = ttk.Button(
arithmetic_frame, text="/", command=partial(enterText, "/")
)
button_multiply: ttk.Button = ttk.Button(
arithmetic_frame, text="*", command=partial(enterText, "*")
)
button_subtract: ttk.Button = ttk.Button(
arithmetic_frame, text="-", command=partial(enterText, "-")
)
button_add: ttk.Button = ttk.Button(
arithmetic_frame, text="+", command=partial(enterText, "+")
)
button_equals: ttk.Button = ttk.Button(
arithmetic_frame, text="=", command=calculate
)
# - Button layout
button_7.grid(row=1, column=1, sticky="nsew")
button_8.grid(row=1, column=2, sticky="nsew")
button_9.grid(row=1, column=3, sticky="nsew")
button_divide.grid(row=1, column=4, sticky="nsew")
button_4.grid(row=2, column=1, sticky="nsew")
button_5.grid(row=2, column=2, sticky="nsew")
button_6.grid(row=2, column=3, sticky="nsew")
button_multiply.grid(row=2, column=4, sticky="nsew")
button_1.grid(row=3, column=1, sticky="nsew")
button_2.grid(row=3, column=2, sticky="nsew")
button_3.grid(row=3, column=3, sticky="nsew")
button_subtract.grid(row=3, column=4, sticky="nsew")
button_0.grid(row=4, column=1, sticky="nsew")
button_decimal.grid(row=4, column=2, sticky="nsew")
button_equals.grid(row=4, column=3, sticky="nsew")
button_add.grid(row=4, column=4, sticky="nsew")
arithmetic_frame.columnconfigure(0, weight=1)
arithmetic_frame.rowconfigure(0, weight=1)
# --- Finalizing
# Bind return key to calculate function
expression_entry.bind("<Return>", calculate) # ty:ignore[no-matching-overload]
# --- Start main loop
root.mainloop()