Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
387: Building a Password Manager GUI with tkinter
When most people first dive into building a GUI for a tool like a password manager, they fall into a specific trap: they treat the GUI as the program itself. I've seen this countless times. A learner will write a 200-line function tied to a "Save Password" button that handles the input validation, encrypts the string, opens a file, writes the data, and then updates a label to say "Success!"
The "Put Everything in the Button" Trap
The problem with shoving your business logic—the actual "work" of managing passwords—inside a tkinter callback is that your code becomes brittle. If you decide later that you want to move from a local text file to an SQLite database, or if you want to add a command-line interface version of your tool, you can't. You'd have to rip the encryption and file logic out of the command=save_password function and rewrite it all.
# The Wrong Way: Logic trapped in the GUI
def save_password_button_clicked():
site = site_entry.get()
pwd = pwd_entry.get()
# Logic is trapped here!
with open("passwords.txt", "a") as f:
f.write(f"{site}|{pwd}\n")
status_label.config(text="Saved!")
If that file write fails because of a permissions error, your entire GUI freezes or crashes because the "view" is too busy trying to be the "database."
Decoupling Your Vault Logic from Your Windows
The professional approach is to separate the Logic (what the app does) from the Interface (how the user sees it). I like to think of the Logic as a "black box." The GUI should just send data into the box and wait for a result. It shouldn't care how the password is encrypted or where it's stored.
Let's look at how we structure this. First, we build a PasswordVault class that knows nothing about tkinter. Then, we build the PasswordApp class that handles the windows and buttons.
import tkinter as tk
from tkinter import messagebox
# THE LOGIC: This could be moved to a separate file entirely
class PasswordVault:
def __init__(self, filename="vault.txt"):
self.filename = filename
def add_password(self, site, password):
# In a real app, you'd encrypt 'password' here
with open(self.filename, "a") as f:
f.write(f"{site}:{password}\n")
return True
def get_all_passwords(self):
try:
with open(self.filename, "r") as f:
return f.readlines()
except FileNotFoundError:
return []
# THE INTERFACE: This only handles widgets and user interaction
class PasswordApp:
def __init__(self, root, vault):
self.root = root
self.vault = vault # We inject the logic dependency here
self.root.title("SecureVault 1.0")
# Entry fields
tk.Label(root, text="Website").grid(row=0, column=0)
self.site_entry = tk.Entry(root)
self.site_entry.grid(row=0, column=1)
tk.Label(root, text="Password").grid(row=1, column=0)
self.pwd_entry = tk.Entry(root, show="*")
self.pwd_entry.grid(row=1, column=1)
# The button calls a handler, which calls the vault
self.save_btn = tk.Button(root, text="Save", command=self.handle_save)
self.save_btn.grid(row=2, column=0, columnspan=2)
def handle_save(self):
site = self.site_entry.get()
pwd = self.pwd_entry.get()
if not site or not pwd:
messagebox.showwarning("Error", "Fields cannot be empty!")
return
# We delegate the hard work to the vault object
if self.vault.add_password(site, pwd):
messagebox.showinfo("Success", "Password stored securely!")
self.site_entry.delete(0, tk.END)
self.pwd_entry.delete(0, tk.END)
# Bootstrap the application
if __name__ == "__main__":
root = tk.Tk()
my_vault = PasswordVault() # Logic
app = PasswordApp(root, my_vault) # Interface
root.mainloop()
Wiring Up the tkinter Interface
Notice how PasswordApp doesn't actually know how to write to a file? It just calls self.vault.add_password(). This is called Dependency Injection. It's a fancy term, but it just means we're giving the GUI the tools it needs to do its job without making it responsible for creating those tools.
I've used grid() here instead of pack() because password managers usually look like forms, and grids are far superior for alignment. Also, notice the show="*" argument in the password entry—never forget that. There's nothing worse than a "security" tool that broadcasts passwords to everyone walking past your monitor.
📋 Practical Task
Implementing a "View All Passwords" Listbox
Your current password manager can save passwords, but it can't show them back to the user. Your task is to extend the PasswordApp class to include a way to view stored passwords.
Requirements:
- Add a
tk.Listboxwidget to thePasswordAppGUI, placed below the save button. - Add a "Refresh List" button that, when clicked, calls
self.vault.get_all_passwords(). - The "Refresh List" handler must clear the current contents of the Listbox (using
delete(0, tk.END)) and then populate it with the current list of saved sites and passwords from the vault. - Ensure the Listbox is scrollable or has a fixed height so it doesn't push the window off the screen.
There are no comments for now.