In this tutorial, we’ll walk through the process of creating an advanced scientific calculator using Python and the ttkbootstrap library. Our calculator will feature both basic and scientific modes, a sleek user interface, and a menu bar for easy navigation. By the end of this tutorial, you’ll have a fully functional calculator that you can use or further customize to your needs.
Prerequisites
Before we begin, make sure you have:
- Python installed on your system (version 3.6 or later)
- Basic knowledge of Python programming
- Familiarity with Tkinter (though not strictly necessary)Step 1: Setting Up the Environment
Step 1: Setting Up the Environment
First, we need to install the ttkbootstrap library. Open your terminal or command prompt and run:
pip install ttkbootstrap
ShellSessionThis library will give our calculator a modern, attractive appearance.
Step 2: Creating the Basic Structure
Let’s start by creating the basic structure of our calculator. Create a new Python file named advanced_calculator.py
and add the following code:
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import math
class AdvancedCalculator:
def __init__(self, master):
self.master = master
master.title("Advanced Calculator")
master.geometry("400x500")
master.resizable(False, False)
style = ttk.Style("darkly")
# We'll add more code here later
if __name__ == "__main__":
root = ttk.Window()
calculator = AdvancedCalculator(root)
root.mainloop()
PythonThis code sets up the main window for our calculator and applies the “darkly” theme from ttkbootstrap.
Step 3: Adding the Menu Bar
Next, let’s add a menu bar to our calculator. Add this method to the AdvancedCalculator
class:
def create_menu(self):
menubar = ttk.Menu(self.master)
self.master.config(menu=menubar)
mode_menu = ttk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Mode", menu=mode_menu)
mode_menu.add_command(label="Basic", command=lambda: self.notebook.select(0))
mode_menu.add_command(label="Scientific", command=lambda: self.notebook.select(1))
help_menu = ttk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Help", menu=help_menu)
help_menu.add_command(label="About", command=self.show_about)
PythonDon’t forget to call self.create_menu()
in the __init__
method.
Step 4: Creating the Calculator Modes
We’ll use a notebook widget to switch between basic and scientific modes. Add this code to the __init__
method:
self.notebook = ttk.Notebook(master)
self.notebook.pack(fill=BOTH, expand=True, padx=5, pady=5)
self.basic_frame = ttk.Frame(self.notebook)
self.scientific_frame = ttk.Frame(self.notebook)
self.notebook.add(self.basic_frame, text="Basic")
self.notebook.add(self.scientific_frame, text="Scientific")
self.create_basic_calculator(self.basic_frame)
self.create_scientific_calculator(self.scientific_frame)
PythonStep 5: Implementing the Basic Calculator
Add this method to create the basic calculator:
def create_basic_calculator(self, parent):
self.basic_display = ttk.Entry(parent, font=("Helvetica", 20), justify='right')
self.basic_display.pack(fill=X, padx=5, pady=5, ipady=10)
button_frame = ttk.Frame(parent)
button_frame.pack(fill=BOTH, expand=True)
buttons = [
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', 'C', '+'
]
row, col = 0, 0
for button in buttons:
cmd = lambda x=button: self.click(x, self.basic_display)
ttk.Button(button_frame, text=button, command=cmd,
style='success.TButton' if button in '/*-+' else 'primary.TButton').grid(row=row, column=col, sticky="nsew", padx=2, pady=2)
col += 1
if col > 3:
col = 0
row += 1
ttk.Button(button_frame, text='=', command=lambda: self.calculate(self.basic_display),
style='warning.TButton').grid(row=row, column=0, columnspan=4, sticky="nsew", padx=2, pady=2)
for i in range(5):
button_frame.grid_rowconfigure(i, weight=1)
for i in range(4):
button_frame.grid_columnconfigure(i, weight=1)
PythonStep 6: Implementing the Scientific Calculator
The scientific calculator is similar, but with additional buttons:
def create_scientific_calculator(self, parent):
self.scientific_display = ttk.Entry(parent, font=("Helvetica", 20), justify='right')
self.scientific_display.pack(fill=X, padx=5, pady=5, ipady=10)
button_frame = ttk.Frame(parent)
button_frame.pack(fill=BOTH, expand=True)
buttons = [
'sin', 'cos', 'tan', 'log',
'(', ')', 'exp', 'sqrt',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', 'C', '+'
]
row, col = 0, 0
for button in buttons:
cmd = lambda x=button: self.click(x, self.scientific_display)
style = 'success.TButton' if button in '/*-+' else 'info.TButton' if button in ['sin', 'cos', 'tan', 'log', 'exp', 'sqrt'] else 'primary.TButton'
ttk.Button(button_frame, text=button, command=cmd, style=style).grid(row=row, column=col, sticky="nsew", padx=2, pady=2)
col += 1
if col > 3:
col = 0
row += 1
ttk.Button(button_frame, text='=', command=lambda: self.calculate(self.scientific_display),
style='warning.TButton').grid(row=row, column=0, columnspan=4, sticky="nsew", padx=2, pady=2)
for i in range(7):
button_frame.grid_rowconfigure(i, weight=1)
for i in range(4):
button_frame.grid_columnconfigure(i, weight=1)
PythonStep 7: Implementing Calculator Logic
Now, let’s add the methods to handle button clicks and calculations:
def click(self, key, display):
if key == 'C':
display.delete(0, END)
else:
if key in ['sin', 'cos', 'tan', 'log', 'sqrt']:
display.insert(END, key + '(')
else:
display.insert(END, key)
def calculate(self, display):
try:
expression = display.get()
expression = expression.replace('sqrt', 'math.sqrt')
expression = expression.replace('sin', 'math.sin')
expression = expression.replace('cos', 'math.cos')
expression = expression.replace('tan', 'math.tan')
expression = expression.replace('log', 'math.log10')
expression = expression.replace('exp', 'math.exp')
result = eval(expression)
display.delete(0, END)
display.insert(END, str(result))
except:
display.delete(0, END)
display.insert(END, "Error")
PythonStep 8: Adding the About Dialog
Finally, let’s add a simple about dialog:
def show_about(self):
about_window = ttk.Toplevel(self.master)
about_window.title("About")
ttk.Label(about_window, text="Advanced Calculator\nCreated with ttkbootstrap", justify=CENTER).pack(padx=20, pady=20)
PythonPutting All Together
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import math
class AdvancedCalculator:
def __init__(self, master):
self.master = master
master.title("Advanced Calculator")
master.geometry("400x500")
master.resizable(False, False)
style = ttk.Style("darkly")
self.create_menu()
self.notebook = ttk.Notebook(master)
self.notebook.pack(fill=BOTH, expand=True, padx=5, pady=5)
self.basic_frame = ttk.Frame(self.notebook)
self.scientific_frame = ttk.Frame(self.notebook)
self.notebook.add(self.basic_frame, text="Basic")
self.notebook.add(self.scientific_frame, text="Scientific")
self.create_basic_calculator(self.basic_frame)
self.create_scientific_calculator(self.scientific_frame)
def create_menu(self):
menubar = ttk.Menu(self.master)
self.master.config(menu=menubar)
mode_menu = ttk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Mode", menu=mode_menu)
mode_menu.add_command(label="Basic", command=lambda: self.notebook.select(0))
mode_menu.add_command(label="Scientific", command=lambda: self.notebook.select(1))
help_menu = ttk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="Help", menu=help_menu)
help_menu.add_command(label="About", command=self.show_about)
def create_basic_calculator(self, parent):
self.basic_display = ttk.Entry(parent, font=("Helvetica", 20), justify='right')
self.basic_display.pack(fill=X, padx=5, pady=5, ipady=10)
button_frame = ttk.Frame(parent)
button_frame.pack(fill=BOTH, expand=True)
buttons = [
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', 'C', '+'
]
row, col = 0, 0
for button in buttons:
cmd = lambda x=button: self.click(x, self.basic_display)
ttk.Button(button_frame, text=button, command=cmd, style='success.TButton' if button in '/*-+' else 'primary.TButton').grid(row=row, column=col, sticky="nsew", padx=2, pady=2)
col += 1
if col > 3:
col = 0
row += 1
ttk.Button(button_frame, text='=', command=lambda: self.calculate(self.basic_display), style='warning.TButton').grid(row=row, column=0, columnspan=4, sticky="nsew", padx=2, pady=2)
for i in range(5):
button_frame.grid_rowconfigure(i, weight=1)
for i in range(4):
button_frame.grid_columnconfigure(i, weight=1)
def create_scientific_calculator(self, parent):
self.scientific_display = ttk.Entry(parent, font=("Helvetica", 20), justify='right')
self.scientific_display.pack(fill=X, padx=5, pady=5, ipady=10)
button_frame = ttk.Frame(parent)
button_frame.pack(fill=BOTH, expand=True)
buttons = [
'sin', 'cos', 'tan', 'log',
'(', ')', 'exp', 'sqrt',
'7', '8', '9', '/',
'4', '5', '6', '*',
'1', '2', '3', '-',
'0', '.', 'C', '+'
]
row, col = 0, 0
for button in buttons:
cmd = lambda x=button: self.click(x, self.scientific_display)
style = 'success.TButton' if button in '/*-+' else 'info.TButton' if button in ['sin', 'cos', 'tan', 'log', 'exp', 'sqrt'] else 'primary.TButton'
ttk.Button(button_frame, text=button, command=cmd, style=style).grid(row=row, column=col, sticky="nsew", padx=2, pady=2)
col += 1
if col > 3:
col = 0
row += 1
ttk.Button(button_frame, text='=', command=lambda: self.calculate(self.scientific_display), style='warning.TButton').grid(row=row, column=0, columnspan=4, sticky="nsew", padx=2, pady=2)
for i in range(7):
button_frame.grid_rowconfigure(i, weight=1)
for i in range(4):
button_frame.grid_columnconfigure(i, weight=1)
def click(self, key, display):
if key == 'C':
display.delete(0, END)
else:
if key in ['sin', 'cos', 'tan', 'log', 'sqrt']:
display.insert(END, key + '(')
else:
display.insert(END, key)
def calculate(self, display):
try:
expression = display.get()
expression = expression.replace('sqrt', 'math.sqrt')
expression = expression.replace('sin', 'math.sin')
expression = expression.replace('cos', 'math.cos')
expression = expression.replace('tan', 'math.tan')
expression = expression.replace('log', 'math.log10')
expression = expression.replace('exp', 'math.exp')
result = eval(expression)
display.delete(0, END)
display.insert(END, str(result))
except:
display.delete(0, END)
display.insert(END, "Error")
def show_about(self):
about_window = ttk.Toplevel(self.master)
about_window.title("About")
ttk.Label(about_window, text="Advanced Calculator\nCreated with ttkbootstrap", justify=CENTER).pack(padx=20, pady=20)
if __name__ == "__main__":
root = ttk.Window()
calculator = AdvancedCalculator(root)
root.mainloop()
PythonConclution
Congratulations! You’ve now created an advanced scientific calculator using Python and ttkbootstrap. This calculator features both basic and scientific modes, a clean and modern interface, and a menu bar for easy navigation.
Feel free to customize and expand upon this calculator to suit your needs. Happy coding!