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:

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
ShellSession

This 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()
Python

This 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)
Python

Don’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)
Python

Step 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)
Python

Step 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)
Python

Step 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")
Python

Step 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)
Python

Putting 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()
Python

Conclution

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!

Leave a Reply

Your email address will not be published. Required fields are marked *