🎲 Build a Random Username Generator in Python with Tkinter
Source: Dev.to
🎲 Random Username Generator – Tutorial
In this tutorial we’ll build a Random Username Generator using Python, Tkinter, and threading. The app lets users generate usernames in different styles, filter, sort, and copy them easily. We’ll break it into digestible steps for beginners.
1️⃣ Setting Up the Project
- Create a new Python file called
username_generator.py. - Make sure you have Python 3.9+ installed.
Imports
import os
import json
import random
import string
import tkinter as tk
from tkinter import ttk, messagebox
import sv_ttk # pip install sv-ttk
from threading import Thread
Explanation
| Module | Purpose |
|---|---|
os & json | Save and load usernames from a file. |
random & string | Generate random usernames. |
tkinter | Main GUI toolkit. |
sv_ttk | Modern light/dark theme for Tkinter. |
Thread | Run username generation without freezing the GUI. |
2️⃣ Helper Functions
CONFIG_FILE = "usernames_data.json"
def load_usernames():
"""Load saved usernames from a JSON file."""
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return []
def save_usernames(usernames_data):
"""Save usernames to a JSON file."""
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
json.dump(usernames_data, f, ensure_ascii=False, indent=4)
Explanation
load_usernames– Reads usernames from a JSON file if it exists.save_usernames– Writes the current list of usernames to a JSON file.
3️⃣ Generating Random Usernames
def generate_username(length=8, style="Normal"):
"""Generate a username based on the selected style."""
if style == "Normal":
chars = string.ascii_letters + string.digits
elif style == "Lowercase":
chars = string.ascii_lowercase + string.digits
elif style == "Uppercase":
chars = string.ascii_uppercase + string.digits
elif style == "NumberEnd":
name = ''.join(random.choice(string.ascii_letters) for _ in range(length - 1))
return name + random.choice(string.digits)
else:
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(length))
Explanation
| Style | Description |
|---|---|
| Normal | Letters (both cases) + numbers |
| Lowercase | Only lowercase letters + numbers |
| Uppercase | Only uppercase letters + numbers |
| NumberEnd | Ends with a number |
4️⃣ Setting Up the Main Window
root = tk.Tk()
root.title("🎲 Random Username Generator Pro")
root.geometry("970x600")
sv_ttk.set_theme("light") # Optional: modern theme
root.title– Sets the window title.root.geometry– Sets the window size.sv_ttk.set_theme– Gives the GUI a modern look.
5️⃣ Global Variables
usernames_data = load_usernames()
filtered_usernames = usernames_data.copy()
current_filter = tk.StringVar(value="")
current_sort = tk.StringVar(value="Alphabetical")
current_style = tk.StringVar(value="Normal")
usernames_data– All usernames (saved + generated).filtered_usernames– Usernames displayed after filtering.current_filter– Tracks the filter text.current_sort– Tracks the selected sorting method.current_style– Tracks the username style.
6️⃣ Adding Username Functions
Generate in a Thread
def add_username_thread(length, count, style):
"""Generate usernames without freezing the GUI."""
def task():
global usernames_data
for _ in range(count):
usernames_data.append(generate_username(length, style))
save_usernames(usernames_data)
apply_filter_sort()
set_status(f"Generated {count} username(s).")
Thread(target=task, daemon=True).start()
Runs username generation in a background thread, keeping the GUI responsive.
Other Functions
def clear_usernames():
if messagebox.askyesno("Confirm", "Clear all saved usernames?"):
usernames_data.clear()
apply_filter_sort()
save_usernames(usernames_data)
set_status("All usernames cleared.")
def copy_selected(event=None):
try:
value = username_text.get("sel.first", "sel.last")
root.clipboard_clear()
root.clipboard_append(value)
set_status(f"Copied '{value}' to clipboard.")
except tk.TclError:
set_status("No selection to copy.")
clear_usernames– Deletes all usernames after confirmation.copy_selected– Copies highlighted text to the clipboard.
Filter & Sort
def apply_filter_sort(*args):
global filtered_usernames
filter_text = current_filter.get().lower()
# Filtering
filtered_usernames = (
[u for u in usernames_data if filter_text in u.lower()]
if filter_text else usernames_data.copy()
)
# Sorting
if current_sort.get() == "Alphabetical":
filtered_usernames.sort()
elif current_sort.get() == "Length (Short → Long)":
filtered_usernames.sort(key=len)
elif current_sort.get() == "Length (Long → Short)":
filtered_usernames.sort(key=len, reverse=True)
update_username_text(filter_text)
Filters usernames based on the input and sorts them alphabetically or by length.
7️⃣ Setting Up the GUI Layout
# ----- Main container -------------------------------------------------
main_frame = ttk.Frame(root, padding=20)
main_frame.pack(expand=True, fill="both")
ttk.Label(
main_frame,
text="🎲 Random Username Generator Pro",
font=("Segoe UI", 22, "bold")
).pack(pady=(0, 10))
# ----- Settings frame --------------------------------------------------
input_frame = ttk.LabelFrame(main_frame, text="Settings", padding=10)
input_frame.pack(fill="x", pady=5)
# Length
ttk.Label(input_frame, text="Length:").grid(row=0, column=0, sticky="w")
length_entry = ttk.Entry(input_frame, width=10)
length_entry.grid(row=0, column=1, padx=5)
length_entry.insert(0, "8")
# Count
ttk.Label(input_frame, text="Count:").grid(row=0, column=2, sticky="w")
count_entry = ttk.Entry(input_frame, width=10)
count_entry.grid(row=0, column=3, padx=5)
count_entry.insert(0, "10")
# Style (dropdown)
ttk.Label(input_frame, text="Style:").grid(row=0, column=4, sticky="w")
style_combo = ttk.Combobox(
input_frame,
textvariable=current_style,
values=["Normal", "Lowercase", "Uppercase", "NumberEnd"],
state="readonly",
width=12
)
style_combo.grid(row=0, column=5, padx=5)
style_combo.current(0)
# ----- Buttons ---------------------------------------------------------
button_frame = ttk.Frame(main_frame, padding=(0, 10))
button_frame.pack(fill="x")
generate_btn = ttk.Button(
button_frame,
text="Generate",
command=lambda: add_username_thread(
int(length_entry.get()),
int(count_entry.get()),
current_style.get()
)
)
generate_btn.pack(side="left", padx=5)
clear_btn = ttk.Button(button_frame, text="Clear All", command=clear_usernames)
clear_btn.pack(side="left", padx=5)
copy_btn = ttk.Button(button_frame, text="Copy Selected", command=copy_selected)
copy_btn.pack(side="left", padx=5)
# ----- Username display (scrollable Text widget) -----------------------
display_frame = ttk.LabelFrame(main_frame, text="Usernames", padding=10)
display_frame.pack(expand=True, fill="both", pady=5)
username_text = tk.Text(display_frame, wrap="none", height=15)
username_text.pack(side="left", expand=True, fill="both")
scroll_y = ttk.Scrollbar(display_frame, orient="vertical", command=username_text.yview)
scroll_y.pack(side="right", fill="y")
username_text.configure(yscrollcommand=scroll_y.set)
# ----- Filter & Sort ---------------------------------------------------
filter_frame = ttk.LabelFrame(main_frame, text="Filter / Sort", padding=10)
filter_frame.pack(fill="x", pady=5)
ttk.Label(filter_frame, text="Filter:").grid(row=0, column=0, sticky="w")
filter_entry = ttk.Entry(filter_frame, textvariable=current_filter, width=30)
filter_entry.grid(row=0, column=1, padx=5)
ttk.Label(filter_frame, text="Sort:").grid(row=0, column=2, sticky="w")
sort_combo = ttk.Combobox(
filter_frame,
textvariable=current_sort,
values=["Alphabetical", "Length (Short → Long)", "Length (Long → Short)"],
state="readonly",
width=20
)
sort_combo.grid(row=0, column=3, padx=5)
sort_combo.current(0)
# Bind filter/sort changes
current_filter.trace_add("write", apply_filter_sort)
current_sort.trace_add("write", apply_filter_sort)
# ----- Status bar -------------------------------------------------------
status_var = tk.StringVar(value="Ready.")
status_bar = ttk.Label(root, textvariable=status_var, relief="sunken", anchor="w")
status_bar.pack(fill="x", side="bottom")
def set_status(message: str):
status_var.set(message)
root.after(3000, lambda: status_var.set("Ready."))
The layout consists of:
- Settings – Length, Count, and Style.
- Buttons – Generate, Clear All, Copy Selected.
- Usernames – Scrollable
Textwidget showing generated usernames. - Filter / Sort – Live filter entry and sort dropdown.
- Status bar – Shows short messages (e.g., “Generated 10 username(s)”).
8️⃣ Run the Application
if __name__ == "__main__":
apply_filter_sort() # Populate the display on start
root.mainloop()
That’s it! You now have a fully functional Random Username Generator with a modern UI, background processing, filtering, sorting, and clipboard support. Feel free to experiment with additional styles or export options. Happy coding!
1️⃣ Imports & Setup
import tkinter as tk
from tkinter import ttk
import random
import string
2️⃣ Helper Functions
def generate_usernames():
# Your generation logic here
...
def clear_usernames():
# Clear the text widget
...
def copy_selected(event=None):
# Copy selected text to clipboard
...
def apply_filter_sort():
# Filter and sort usernames
...
3️⃣ Main Window
root = tk.Tk()
root.title("Username Generator")
root.geometry("800x600")
4️⃣ Main Frame
main_frame = ttk.Frame(root, padding=10)
main_frame.pack(expand=True, fill="both")
5️⃣ Input Section
input_frame = ttk.Frame(main_frame)
input_frame.pack(fill="x", pady=5)
# Length
ttk.Label(input_frame, text="Length:").grid(row=0, column=0, sticky="e")
length_var = tk.IntVar(value=8)
ttk.Entry(input_frame, textvariable=length_var, width=5).grid(row=0, column=1)
# Count
ttk.Label(input_frame, text="Count:").grid(row=0, column=2, sticky="e")
count_var = tk.IntVar(value=10)
ttk.Entry(input_frame, textvariable=count_var, width=5).grid(row=0, column=3)
# Style
ttk.Label(input_frame, text="Style:").grid(row=0, column=4)
current_style = tk.StringVar(value="Normal")
style_combo = ttk.Combobox(
input_frame,
state="readonly",
textvariable=current_style,
width=20,
values=["Normal", "Lowercase", "Uppercase", "NumberEnd"]
)
style_combo.grid(row=0, column=5)
Explanation
| Widget | Purpose |
|---|---|
ttk.Frame | Organises the layout. |
ttk.Entry | Input fields for length and count. |
ttk.Combobox | Dropdown for username style. |
6️⃣ Buttons
ttk.Button(input_frame, text="Generate", command=generate_usernames)\
.grid(row=0, column=6, padx=5)
ttk.Button(input_frame, text="Clear All", command=clear_usernames)\
.grid(row=0, column=7, padx=5)
ttk.Button(input_frame, text="Copy Selected", command=copy_selected)\
.grid(row=0, column=8, padx=5)
Explanation
| Button | Action |
|---|---|
| Generate | Calls generate_usernames to create usernames. |
| Clear All | Deletes all usernames from the display. |
| Copy Selected | Copies highlighted text to the clipboard. |
7️⃣ Display Area with Scrollbar
text_frame = ttk.Frame(main_frame)
text_frame.pack(expand=True, fill="both", pady=10)
username_text = tk.Text(
text_frame,
font=("Segoe UI", 12),
state=tk.DISABLED,
wrap="none",
height=10
)
username_text.pack(side="left", expand=True, fill="both")
scrollbar = ttk.Scrollbar(text_frame, orient="vertical", command=username_text.yview)
scrollbar.pack(side="right", fill="y")
username_text.config(yscrollcommand=scrollbar.set)
username_text.bind("", copy_selected)
Explanation
| Component | Purpose |
|---|---|
tk.Text | Displays generated usernames. |
ttk.Scrollbar | Allows scrolling through many usernames. |
8️⃣ Status Bar & Total Count
total_var = tk.StringVar(value=f"Total Usernames: {len(filtered_usernames)}")
ttk.Label(main_frame, textvariable=total_var, font=("Segoe UI", 12)).pack()
status_var = tk.StringVar(value="Ready")
ttk.Label(root, textvariable=status_var, anchor="w").pack(side="bottom", fill="x")
Explanation
Shows the total number of usernames and status messages such as “Copied” or “Generated”.
9️⃣ Run the App
apply_filter_sort() # Load existing usernames (if any)
root.mainloop() # Start the GUI event loop
Congratulations! 🎉 Your username generator GUI is now ready to use.