Affichage des articles dont le libellé est Python Projects. Afficher tous les articles
Affichage des articles dont le libellé est Python Projects. Afficher tous les articles

Python To-Do List Project Source Code

How to Create To Do List Project In Python Tkinter


How to Create To Do List Project In Python Tkinter



In this Python Tutorial we will see How To Create a To Do List Project in Python using Tkinter.
This application provides a modern interface for managing tasks, allowing users to add, view, delete tasks, and Complete/Completed toggle button .

What We Are Gonna Use In This Project:

- Python Tkinter: GUI framework.
- Visual Studio Editor.





Project Source Code:



     - Build the user interface

Calculates screen dimensions and positions the application window at the center of the user's display.


def center_window(self):
"""Center the window on the screen."""
# Get screen dimensions
screen_width = self.root.winfo_screenwidth()
screen_height = self.root.winfo_screenheight()

# Calculate position
x = (screen_width - 900) // 2
y = (screen_height - 600) // 2

# Set window position
self.root.geometry(f"900x600+{x}+{y}")



     - Custom Window

Creates a custom title bar with application branding and window controls, replacing the default system title bar.


def setup_title_bar(self):
"""Create custom title bar with controls."""
self.title_bar = tk.Frame(self.root, bg=self.special_color, height=40)
self.title_bar.pack(fill=tk.X)

# Application title
title = tk.Label(self.title_bar, text="Tasks Manager",
font=self.title_font,
bg=self.special_color, fg="white")
title.pack(side=tk.LEFT, padx=15)

# Window controls container
controls = tk.Frame(self.title_bar, bg=self.special_color)
controls.pack(side=tk.RIGHT, padx=5)

# Control buttons
buttons = [
("□", lambda: self.toggle_maximize(), "#64748b"),
("x", lambda: self.root.destroy(), "#ef4444")
]

for symbol, command, hover_color, in buttons:
btn = tk.Label(controls, text=symbol, bg=self.special_color,
fg="white", font=self.title_font, padx=10)
btn.pack(side=tk.LEFT)
# Hover effects
btn.bind("<Enter>", lambda e,
color=hover_color: e.widget.configure(bg=color))
btn.bind("<Leave>", lambda e: e.widget.configure(bg=self.special_color))
btn.bind("<Button-1>", lambda e, cmd=command: cmd())



     - Window State Management

Toggles between maximized and normal window states when users click the maximize button.


def toggle_maximize(self):
"""Toggle between maximized and normal window state."""
if self.root.state() == 'zoomed':
self.root.state('normal')

else:
self.root.state('zoomed')



     - Bottom Control Panel

Creates the bottom action bar containing the primary "Add New Task" button with hover animations.


def setup_action_bar(self):
"""Create the bottom action bar with controls."""
action_bar = tk.Frame(self.root, bg=self.bg_color, height=60)
action_bar.pack(fill=tk.X, padx=20, pady=(0, 20))

# Add task button
add_btn = tk.Button(action_bar, text="+ Add New Task",
font=self.button_font, bg=self.special_color,
fg="white", border=0, padx=20, pady=10,
command=self.add_task, cursor="hand2")
add_btn.pack(side=tk.LEFT)

# Hover effect
add_btn.bind("<Enter>", lambda e: e.widget.configure(bg="#1d4ed8"))
add_btn.bind("<Leave>", lambda e: e.widget.configure(bg=self.special_color))



     - Drag Functionality Setup

Configures mouse event bindings to enable window dragging from the title bar.


def setup_window_drag(self):
"""Configure window dragging functionality."""
self.title_bar.bind("<Button-1>", self.on_drag_start)
self.title_bar.bind("<B1-Motion>", self.on_drag_motion)



     - Drag Initialization

Captures initial mouse coordinates when the user starts dragging the window.


def on_drag_start(self, event):
"""Store initial coordinates when starting drag."""
self.drag_data = (event.x_root - self.root.winfo_x(),
event.y_root - self.root.winfo_y())



     - Drag Position Updates

Continuously updates window position as the user drags the mouse across the screen.


def on_drag_motion(self, event):
"""Update window position during drag."""
x = event.x_root - self.drag_data[0]
y = event.y_root - self.drag_data[1]
self.root.geometry(f"+{x}+{y}")



     - Scrollable Content Area

Creates a scrollable canvas system for displaying task cards when content exceeds window height.


def setup_scrollable_canvas(self):
"""Create a scrollable canvas for task cards."""
# Create canvas with scrollbar
self.canvas =tk.Canvas(self.content_frame, bg=self.bg_color,
highlightthickness=0)
scrollbar = ttk.Scrollbar(self.content_frame, orient="vertical",
command=self.canvas.yview)
# Configure canvas scroll region
self.canvas.configure(yscrollcommand=scrollbar.set)
# Create frame for task cards
self.dashboard_panel = tk.Frame(self.canvas, bg=self.bg_color)

# Pack elements
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Create window in canvas for dashboard
self.canvas_window = self.canvas.create_window((0,0),
window=self.dashboard_panel, anchor="nw")

# Configure canvas scrolling
self.canvas.bind("<Configure>", self.on_canvas_configure)
self.dashboard_panel.bind("<Configure>", self.on_frame_configure)
self.canvas.bind_all("<MouseWheel>", self.on_mousewheel)



     - Canvas Resize Handler

Updates the canvas scroll region and content width when the canvas is resized.


def on_canvas_configure(self, event):
"""Update canvas scroll region when canvas is configured."""
self.canvas.configure(scrollregion=self.canvas.bbox("all"))
width = event.width
self.canvas.itemconfig(self.canvas_window, width=width)



     - Frame Resize Handler

Recalculates scroll boundaries when the inner frame content changes size.


def on_frame_configure(self, event):
"""Update canvas scroll region when frame is configured."""
self.canvas.configure(scrollregion=self.canvas.bbox("all"))



     - Mouse Wheel Scrolling

Enables mouse wheel scrolling through the task list.


def on_mousewheel(self, event):
"""Handle mouse wheel scrolling."""
self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")



     - Task Creation

Handles new task creation with validation, modal dialog presentation, and task limit enforcement (12-task maximum limit).


def add_task(self):
"""Add a new task with modern dialog."""
if len(self.tasks) >= 12:
self.show_error("Maximum Tasks Reached",
                            "Please Complete Tasks Before Adding New Ones")
return
dialog = ModernInputDialog(self.root, "Add New Task", "Enter task details")
self.root.wait_window(dialog)

if dialog.result:
task = {
'text': dialog.result,
'date': datetime.now().strftime("%b %d, %Y"),
'status':'pending'
}
self.tasks.append(task)
self.update_task_panel()


     - UI Refresh

Rebuilds the entire task display panel, organizing tasks into horizontal tiers with proper spacing.


def update_task_panel(self):
"""Refresh the task display with styling."""
for widget in self.dashboard_panel.winfo_children():
widget.destroy()

for i, task in enumerate(self.tasks):
if i % self.tasks_per_tier == 0:
tier_frame = tk.Frame(self.dashboard_panel, bg = self.bg_color)
tier_frame.pack(fill = tk.X, pady = (10, 0))
self.create_task_card(tier_frame, task)



     - Individual Task UI

Generates individual task cards with completion status, action buttons, and custom styling.


def create_task_card(self, parent, task):
"""Create a task card with completion status."""
card = tk.Frame(parent, bg=self.card_bg, padx = 15, pady = 15,
highlightthickness = 1,
highlightbackground = "#e2eff0")
card.pack(side=tk.LEFT, padx = 10, pady = 10,
fill=tk.BOTH, expand=True)

header = tk.Frame(card, bg = self.card_bg)
header.pack(fill=tk.X, pady=(0, 10))

# Use completed font if task is marked as completed
task_font = self.completed_font if task.get('completed', False)
else self.text_font
task_label = tk.Label(header, text = task['text'],
font = task_font, bg = self.card_bg,
fg = self.text_color, wraplength = 200,
justify = tk.LEFT)
task_label.pack(side = tk.LEFT, anchor = "w")

tk.Label(card, text = task['date'], font = ("Helvatica", 9),
bg = self.card_bg, fg = "#64748b").pack(anchor="w")

btn_frame = tk.Frame(card, bg = self.card_bg)
btn_frame.pack(fill = tk.X, pady = (10, 0))

# Change complete button text based on completion status
complete_text = "✓ Completed" if task.get('completed', False)
else "✓ Complete"

complete_btn = tk.Button(btn_frame, text = complete_text,
font = self.button_font,
bg = "#22c55e" if not task.get('completed', False)
else "#64748b",
fg="white", border = 0, padx = 10, pady = 5,
command = lambda: self.toggle_complete_task(
task, task_label, complete_btn))

complete_btn.pack(side = tk.LEFT, padx = (0, 5))

delete_btn = tk.Button(btn_frame, text = "Delete",
font = self.button_font, bg = "#ef4444",
fg="white", border= 0, padx = 10, pady = 5,
command = lambda: self.delete_task(task))

delete_btn.pack(side = tk.LEFT)

for btn, hover_color in [(complete_btn, "#16a34a"), (delete_btn, "#dc2626")]:
btn.bind("<Enter>", lambda e,
color = hover_color: e.widget.configure(bg=color))
btn.bind("<Leave>", lambda e, btn = btn: self.reset_button_color(e, btn))



     - Task Status Management

Handles task completion toggling with success notifications.


def toggle_complete_task(self, task, label, button):
"""Toggle task completion status."""
task['completed'] = not task.get('completed', False)

if task['completed']:
label.configure(font = self.completed_font)
button.configure(text = "✓ Completed", bg="#64748b")
self.show_success("Task Completed", "Grate job completing your task !")
else:
label.configure(font = self.text_font)
button.configure(text = "✓ Complete", bg="#22c55e")



     - Hover State Management

Manages button color states after hover events end.


def reset_button_color(self, event, button):
"""Reset button color after hover."""
if "Complete" in button['text']:
if "Completed" in button['text']:
button.configure(bg = "#64748b")
else:
button.configure(bg = "#22c55e")
else:
button.configure(bg = "#ef4444")



     - Task Removal

Removes tasks from the data structure and triggers UI refresh.


def delete_task(self, task):
"""Remove a task and update display."""
self.tasks.remove(task)
self.update_task_panel()



     - User Notifications

Display system notifications for errors and successful actions using standard message boxes.


def show_error(self, title, message):
"""Display error message"""
messagebox.showerror(title, message)

def show_success(self, title, message):
"""Display error message"""
messagebox.showinfo(title, message)


     - ModernInputDialog Class - Custom Modal Dialog

Display system notifications for errors and successful actions using standard message boxes.


class ModernInputDialog(tk.Toplevel):
"""Custom modern dialog for task input."""
def __init__(self, parent, title, prompt):
super().__init__(parent)

self.result = None

# Configure dialog window
self.title(title)
self.geometry("400x250")
self.configure(bg="#ffffff")
self.resizable(False, False)
self.overrideredirect(True)
self.attributes('-alpha', 0.0)

self.center_on_parent(parent)

self.container = tk.Frame(self, bg="#ffffff",
highlightthickness=1,
highlightbackground="#e2e8f0",
padx=20, pady=20)
self.container.pack(fill=tk.BOTH, expand=True)

title_bar = tk.Frame(self.container, bg="#ffffff")
title_bar.pack(fill=tk.X, pady=(0, 15))

tk.Label(title_bar, text = title, font=("Helvatica", 14, "bold"),
bg="#ffffff",
fg="#1e293b").pack(side=tk.LEFT)

close_btn = tk.Label(title_bar, text = "×", font=("Helvetica", 14),
bg="#ffffff", fg="#64748b", cursor="hand2")
close_btn.pack(side=tk.RIGHT)
close_btn.bind("<Button-1>", lambda e: self.cancel())

tk.Label(self.container, text = prompt, font=("Helvetica", 11),
bg="#ffffff", fg="#1e293b").pack(fill=tk.X)
entry_frame = tk.Frame(self.container, bg="#f1f5f9",
highlightthickness=1,
highlightbackground="#e2e8f0")
entry_frame.pack(fill=tk.X, pady=(10, 20))

self.entry = tk.Entry(entry_frame, font=("Helvetica", 12),
bd=0, bg="#f1f5f9", fg="#1e2936",
insertbackground="#2563eb")
self.entry.pack(fill=tk.X, padx=10, pady=8)
self.entry.focus_set()

btn_frame = tk.Frame(self.container, bg="#ffffff")
btn_frame.pack(fill=tk.X, pady=(0, 10))

# Create modern styled buttons
buttons = [
("Cancel", "#f1f2f9", "#64748b", self.cancel),
("Add Task", "#2563eb", "#ffffff", self.submit)
]

for text, bg, fg, command in buttons:
btn = tk.Button(btn_frame, text=text, font=("Helvetica", 12),
bg=bg, fg=fg, bd=0, padx=20, pady=8, cursor="hand2",
command=command)
btn.pack(side=tk.RIGHT, padx=5)

# Add hover effects
if text == "cancel":
btn.bind("<Enter>", lambda e: e.widget.configure(bg="#e2e8f0"))
btn.bind("<Leave>", lambda e: e.widget.configure(bg="#f1f5f9"))
else:
btn.bind("<Enter>", lambda e: e.widget.configure(bg="#1d4ed8"))
btn.bind("<Leave>", lambda e: e.widget.configure(bg="#2563eb"))

# Add key bindings
self.bind("<Return>", lambda e: self.submit())
self.bind("<Escape>", lambda e: self.cancel())


# Make dialog draggable
title_bar.bind("<Button-1>", self.start_drag)
title_bar.bind("<B1-Motion>", self.drag)

# Fade in animation
self.fade_in()


def fade_in(self):
"""Animate the dialog fading in."""
alpha = self.attributes("-alpha")
if alpha < 1.0:
alpha += 0.1
self.attributes("-alpha", alpha)
self.after(20, self.fade_in)

def fade_out(self):
"""Animate the dialog fading out."""
alpha = self.attributes("-alpha")
if alpha > 0:
alpha -= 0.1
self.attributes("-alpha", alpha)
self.after(20, self.fade_out)
else:
self.destroy()

def submit(self):
"""Handle dialog submission with fade out animation."""
self.result = self.entry.get()
self.fade_out()

def cancel(self):
"""Handle dialog cancellation with fade out animation."""
self.fade_out()

def center_on_parent(self, parent):
"""Center the dialog window on its parent."""
# Get parent window position and size
parent_x = parent.winfo_x()
parent_y = parent.winfo_y()
parent_width = parent.winfo_width()
parent_height = parent.winfo_height()

# Calculate center position
x = parent_x + (parent_width - 400) // 2
y = parent_y + (parent_height - 250) // 2

# Set dialog position
self.geometry(f"400x250+{x}+{y}")


def start_drag(self, event):
"""Store initial coordinates for window dragging."""
self.drag_data = (event.x_root - self.winfo_x(), event.y_root - self.winfo_y())

def drag(self, event):
"""Update window position during drag."""
x = event.x_root - self.drag_data[0]
y = event.y_root - self.drag_data[1]
self.geometry(f"+{x}+{y}")






The Final Result:

Python To-Do List Project Source Code

Python To-Do List Project

Python To-Do List Project In Tkinter

To-Do List Project In Python Tkinter

To-Do List App In Python Tkinter

Tasks Project In Python Tkinter



if you want the source code click on the download button below











Python Banking Project Source Code

How To Create a Banking Application in Python  Tkinter

How To Create a Banking Application in Python  Tkinter


In this Python Tutorial we will see How to Create a simple banking app using Python Tkinter.
In this python tkinter bank project we will create custom panels, buttons and chart, with Real-time balance tracking, Transaction history with visual indicators, Input validation and error handling, Charts showing balance trends .

What We Are Gonna Use In This Project:

- Python Tkinter: Core GUI framework.
- ttkbootstrap: theme system.
- matplotlib: Data visualization for balance history charts.
- NumPy: Numerical operations for chart data.
- Visual Studio Editor.




if you want the source code click on the download button below




Project Source Code:



     - Build the user interface


def create_widgets(self):
"""
Create and arrange all widgets for the application.
"""
# Main frame to hold all other widgets
main_frame = ttk.Frame(self.root, padding="10 10 10 10")
main_frame.pack(fill=tk.BOTH, expand=True)

# Header frame for logo and date
header_frame = ttk.Frame(main_frame)
header_frame.pack(fill=tk.X, pady=(0, 20))

# Logo
logo_label = ttk.Label(header_frame, text="PyBank",
font=("Roboto", 24, "bold"), foreground=ACCENT_COLOR)
logo_label.pack(side=tk.LEFT)

# Current date display
date_label = ttk.Label(header_frame,
text=datetime.datetime.now().strftime("%B %d, %Y"),
font=("Roboto", 12))
date_label.pack(side=tk.RIGHT)

# Content area to hold balance, input, and chart
content_frame = ttk.Frame(main_frame)
content_frame.pack(fill=tk.BOTH, expand=True)

# Balance display card
balance_frame = ttk.Frame(content_frame, style="Card.TFrame")
balance_frame.grid(row=0, column=0, padx=(0, 10), pady=(0, 10), sticky="nsew")

balance_title = ttk.Label(balance_frame, text="Current Balance",
font=("Roboto", 16, "bold"), foreground=ACCENT_COLOR)
balance_title.pack(pady=(10, 5))

self.balance_label = ttk.Label(balance_frame, text="$0.00",
font=("Roboto", 28, "bold"),
foreground=SECONDARY_ACCENT)
self.balance_label.pack(pady=(0, 10))

# Transaction input frame
input_frame = ttk.Frame(content_frame, style="Card.TFrame")
input_frame.grid(row=1, column=0, padx=(0, 10), pady=(0, 10), sticky="nsew")

amount_label = ttk.Label(input_frame, text="Transaction Amount",
font=("Roboto", 14))
amount_label.pack(pady=(10, 5))

self.amount_entry = ttk.Entry(input_frame, font=("Roboto", 14))
self.amount_entry.pack(pady=(0, 10), padx=10, fill=tk.X)

button_frame = ttk.Frame(input_frame)
button_frame.pack(pady=(0, 10), fill=tk.X)

# Custom styled buttons for deposit and withdraw
deposit_btn = ttb.Button(button_frame, text="Deposit",
bootstyle=(SUCCESS, SOLID),
command=lambda: self.handle_transaction("deposit"))
deposit_btn.pack(side=tk.LEFT, padx=(10, 5), fill=tk.X, expand=True)

withdraw_btn = ttb.Button(button_frame, text="Withdraw",
bootstyle=(DANGER, SOLID),
command=lambda: self.handle_transaction("withdraw"))
withdraw_btn.pack(side=tk.RIGHT, padx=(5, 10), fill=tk.X, expand=True)

# Chart area for balance history
self.chart_frame = ttk.Frame(content_frame, style="Card.TFrame")
self.chart_frame.grid(row=0, column=1, rowspan=2, padx=(10, 0),
pady=(0, 10), sticky="nsew")

chart_title = ttk.Label(self.chart_frame, text="Balance History",
font=("Roboto", 16, "bold"),
foreground=ACCENT_COLOR)
chart_title.pack(pady=(10, 5))

self.create_chart()

# Transaction history frame
history_frame = ttk.Frame(content_frame, style="Card.TFrame")
history_frame.grid(row=2, column=0, columnspan=2, sticky="nsew")

history_title = ttk.Label(history_frame, text="Transaction History",
font=("Roboto", 16, "bold"),
foreground=ACCENT_COLOR)
history_title.pack(pady=(10, 5))

# Frame to hold the Treeview and scrollbar
tree_frame = ttk.Frame(history_frame)
tree_frame.pack(pady=(0, 10), padx=10, fill=tk.BOTH, expand=True)

# Create the Treeview for transaction history
self.history_tree = ttk.Treeview(tree_frame,
columns=("Type", "Amount", "Date"),
show="headings", height=8)
self.history_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

# Add a vertical scrollbar to the Treeview
scrollbar = ttk.Scrollbar(tree_frame, orient="vertical",
command=self.history_tree.yview)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
self.history_tree.configure(yscrollcommand=scrollbar.set)

# Configure Treeview columns
self.history_tree.heading("Type", text="Type")
self.history_tree.heading("Amount", text="Amount")
self.history_tree.heading("Date", text="Date")
self.history_tree.column("Type", width=100)
self.history_tree.column("Amount", width=100)
self.history_tree.column("Date", width=150)

# Apply custom styles to the Treeview
self.style_treeview()

# Configure grid weights for responsive layout
content_frame.grid_columnconfigure(0, weight=1)
content_frame.grid_columnconfigure(1, weight=1)
content_frame.grid_rowconfigure(2, weight=1)

    
    

     - Custom Table Styling.

def style_treeview(self):
"""
Apply custom styles to the Treeview widget.
"""
# Configure a modern style for the Treeview
self.style.configure("Treeview",
background="white",
foreground=TEXT_COLOR,
rowheight=30,
fieldbackground="white")
self.style.map('Treeview', background=[('selected', ACCENT_COLOR)])

# Style the Treeview headings
self.style.configure("Treeview.Heading",
background="#EDF2F7",
foreground=TEXT_COLOR,
relief="flat",
font=("Roboto", 11, "bold"))
self.style.map("Treeview.Heading",
background=[('active', '#E2E8F0')])

# Configure tags for deposit and withdraw rows
self.history_tree.tag_configure('deposit', foreground=POSITIVE_COLOR)
self.history_tree.tag_configure('withdraw', foreground=NEGATIVE_COLOR)

        
    

     - Data Visualization Setup.


def create_chart(self):
"""
Create and initialize the balance history chart.
"""
# Create a chart
fig, self.ax = plt.subplots(figsize=(5, 3), facecolor=BACKGROUND_COLOR)

# Create a FigureCanvasTkAgg object and add it to the chart frame
self.canvas = FigureCanvasTkAgg(fig, master=self.chart_frame)
self.canvas.draw()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

# Set the background color of the axis to match the app's background
self.ax.set_facecolor(BACKGROUND_COLOR)

# Style the x and y axis tick labels
self.ax.tick_params(axis='x', colors=TEXT_COLOR)
self.ax.tick_params(axis='y', colors=TEXT_COLOR)

# Style the chart border
for spine in self.ax.spines.values():
spine.set_color('#E2E8F0')

# Initial update of the chart
self.update_chart()

    


     - Dynamic Chart Updates.


def update_chart(self):
"""
Update the balance history chart with current transaction data.
"""
# Clear the previous plot
self.ax.clear()

# Initialize balances list with starting balance of 0
balances = [0]

# Calculate balance history
if len(self.transactions) > 0:

for transaction in self.transactions:

if transaction.type == "deposit":
balances.append(balances[-1] + transaction.amount)

else:
balances.append(balances[-1] - transaction.amount)

# Create x-axis values (transaction indices)
x = range(len(balances))

# Plot the balance history line
self.ax.plot(x, balances, color=ACCENT_COLOR, linewidth=2,
marker='o', markersize=6)

# Fill the area under the line
gradient = np.linspace(0, 1, len(x))
self.ax.fill_between(x, balances, color="red", alpha=0.2)

# Add labels and title
self.ax.set_xlabel('Transactions', color=TEXT_COLOR)
self.ax.set_ylabel('Balance', color=TEXT_COLOR)
#self.ax.set_title('Balance History', color=ACCENT_COLOR, fontweight='bold')

# Style the grid
self.ax.grid(color='#E2E8F0', linestyle='--', linewidth=0.5, alpha=0.7)

# Remove top and right spines
self.ax.spines['right'].set_visible(False)

# Add subtle shadow to the line
shadow_line, = self.ax.plot(x, balances, color='grey',
linewidth=6, alpha=0.2)
shadow_line.set_zorder(self.ax.get_zorder() - 1)

# Add data labels
for i, balance in enumerate(balances):
self.ax.annotate(f'${balance:.2f}', (i, balance),
textcoords="offset points",
xytext=(0,10), ha='center',
fontsize=8, color=TEXT_COLOR)

# Adjust layout and redraw the canvas
plt.tight_layout()
self.canvas.draw()


    


     - Processes both deposit and withdrawal requests with validation and error handling.


def handle_transaction(self, type):
"""
Process a deposit or withdrawal transaction.
"""
try:
amount = float(self.amount_entry.get())
if amount <= 0:
self.show_error("Please enter a valid positive number")
return

if type == "withdraw" and amount > self.balance:
self.show_error("Insufficient funds")
return

if type == "deposit":
self.balance += amount
self.show_success(f"Successfully deposited ${amount:.2f}")

else:
self.balance -= amount
self.show_success(f"Successfully withdrew ${amount:.2f}")
# Add the new transaction to the list
self.transactions.append(Transaction(type, amount))

# Update UI elements
self.update_balance_label()
self.update_history()
self.update_chart()
self.amount_entry.delete(0, tk.END) # Clear the entry field

except ValueError:
self.show_error("Please enter a valid number")




     - Updates the prominently displayed current balance whenever the account balance changes.


def update_balance_label(self):
"""
Update the displayed balance.
"""
self.balance_label.config(text=f"${self.balance:.2f}")

        


     - Refreshes the transaction history table with the latest transactions.


def update_history(self):
"""
Update the transaction history display.
"""
# Clear existing entries
for i in self.history_tree.get_children():
self.history_tree.delete(i)

# Add transactions to the Treeview
for transaction in reversed(self.transactions):
if transaction.type == "deposit":
icon = "↑" # Up arrow for deposit
tag = 'deposit'
else:
icon = "↓" # Down arrow for withdraw
tag = 'withdraw'

self.history_tree.insert("", "end", values=(
f"{icon} {transaction.type.capitalize()}",
f"${transaction.amount:.2f}",
transaction.date.strftime("%Y-%m-%d %H:%M")
), tags=(tag,))

# Apply alternating row colors
for i, item in enumerate(self.history_tree.get_children()):
if i % 2 == 0:
self.history_tree.item(item,
tags=self.history_tree.item(item, "tags") + ('evenrow',))
else:
self.history_tree.item(item,
tags=self.history_tree.item(item, "tags") + ('oddrow',))
# Configure tag colors
self.history_tree.tag_configure('evenrow', background='#F7FAFC')
self.history_tree.tag_configure('oddrow', background='#EDF2F7')

        


     - Creates and displays custom-styled error dialogs when invalid actions are attempted.


def show_error(self, message):
"""
Display an error message to the user.
"""
# Create custom error dialog instead of using ttkbootstrap's Messagebox
error_dialog = tk.Toplevel(self.root)
error_dialog.title("Error")
error_dialog.geometry("450x170")
error_dialog.configure(bg="white")
error_dialog.resizable(False, False)

# Make dialog modal
error_dialog.transient(self.root)
error_dialog.grab_set()

# Center the dialog on the parent window
x = self.root.winfo_x() + (self.root.winfo_width() / 2) - (450 / 2)
y = self.root.winfo_y() + (self.root.winfo_height() / 2) - (170 / 2)
error_dialog.geometry(f"+{int(x)}+{int(y)}")

# Add error icon and message
frame = ttk.Frame(error_dialog)
frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

error_label = ttk.Label(frame, text="⊘ Error", font=("Arial", 17, "bold"),
foreground=NEGATIVE_COLOR)
error_label.pack(pady=(0, 10))

message_label = ttk.Label(frame, text=message, font=("Arial", 14, ""),
wraplength=400)
message_label.pack(pady=(0, 10))

ok_button = tk.Button(frame, text="OK", bg=ACCENT_COLOR, fg="white", width=10,
command=error_dialog.destroy)
ok_button.pack()

        


     - Shows confirmation dialogs when transactions are successfully completed.


def show_success(self, message):
"""
Display a success message to the user.
"""
# Create custom success dialog
success_dialog = tk.Toplevel(self.root)
success_dialog.title("Success")
success_dialog.geometry("450x170")
success_dialog.configure(bg="white")
success_dialog.resizable(False, False)

# Make dialog modal
success_dialog.transient(self.root)
success_dialog.grab_set()

# Center the dialog on the parent window
x = self.root.winfo_x() + (self.root.winfo_width() / 2) - (450 / 2)
y = self.root.winfo_y() + (self.root.winfo_height() / 2) - (170 / 2)
success_dialog.geometry(f"+{int(x)}+{int(y)}")

# Add success icon and message
frame = ttk.Frame(success_dialog)
frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)

success_label = ttk.Label(frame, text="✓ Success", font=("Arial", 17, "bold"),
foreground=SECONDARY_ACCENT)
success_label.pack(pady=(0, 10))

message_label = ttk.Label(frame, text=message, font=("Arial", 14, ""),
wraplength=400)
message_label.pack(pady=(0, 10))

ok_button = tk.Button(frame, text="OK", bg=SECONDARY_ACCENT, fg="white",
width=10, command=success_dialog.destroy)
ok_button.pack()