# To delete a selected row from a Tkinter Treeview and the corresponding record from a MySQL database on a button click, you'll need to follow these steps:
Requirements:
tkinter for GUI
>> pip install tkinter
mysql.connector to interact with MySQL
>> pip install mysql-connector-python
Example Code
import tkinter as tk
from tkinter import ttk, messagebox
import mysql.connector
# Connect to MySQL
db = mysql.connector.connect(
host="localhost",
user="root",
password="Admin@2025",
database="testdb"
)
cursor = db.cursor()
# Sample GUI
root = tk.Tk()
root.title("Delete Row Example")
tree = ttk.Treeview(root, columns=("id", "name"), show="headings")
tree.heading("id", text="ID")
tree.heading("name", text="Name")
tree.pack()
# Sample function to load data into Treeview :
def load_data():
cursor.execute("SELECT id, name FROM your_table")
rows = cursor.fetchall()
for row in rows:
tree.insert("", "end", values=row)
# Function to delete selected row
def delete_selected():
selected_item = tree.selection()
if not selected_item:
messagebox.showwarning("No selection", "Please select a row to delete.")
return
item = tree.item(selected_item)
record_id = item["values"][0] # Assuming the first column is the ID
# Confirm deletion
if not messagebox.askyesno("Confirm", f"Delete record ID {record_id}?"):
return
try:
# Delete from database
cursor.execute("DELETE FROM your_table WHERE id = %s", (record_id,))
db.commit()
# Delete from Treeview
tree.delete(selected_item)
messagebox.showinfo("Success", f"Record ID {record_id} deleted.")
except Exception as e:
messagebox.showerror("Error", f"Failed to delete record: {e}")
db.rollback()
# Delete button
delete_btn = tk.Button(root, text="Delete Selected", command=delete_selected)
delete_btn.pack(pady=10)
load_data()
root.mainloop()
Notes:
Replace your_username, your_password, your_database, and your_table with your actual MySQL credentials and table name.
Ensure the id column is the primary key or a unique identifier for deletion.
@ If record_id is integer ?
Yes, it is perfectly fine to use %s as a placeholder in MySQL queries — even for integers.
In mysql.connector (and most other Python DB-API 2.0-compliant libraries), %s is the correct placeholder regardless of the data type (string, integer, float, etc.).
The library safely handles the parameter substitution.
Example — both valid:
# If record_id is an integer:
record_id = 5
cursor.execute("DELETE FROM your_table WHERE id = %s", (record_id,))
Avoid using string formatting like below:
# This is unsafe and should be avoided (prone to SQL injection)
cursor.execute(f"DELETE FROM your_table WHERE id = {record_id}")
So yes, using %s with integers is correct and safe.
****************************************
# To display a specific record from a MySQL table in a Tkinter Treeview based on an Entry input and button click, here's a full working example:
---
Example: Search by ID and Show in Treeview
import tkinter as tk
from tkinter import ttk, messagebox
import mysql.connector
# --- MySQL Connection ---
db = mysql.connector.connect(
host="localhost",
user="root",
password="Admin@2025",
database="testdb"
)
cursor = db.cursor()
# --- GUI Setup ---
root = tk.Tk()
root.title("Search Record")
# --- Entry and Button ---
search_frame = tk.Frame(root)
search_frame.pack(pady=10)
tk.Label(search_frame, text="Enter ID:").pack(side=tk.LEFT)
id_entry = tk.Entry(search_frame)
id_entry.pack(side=tk.LEFT, padx=5)
# Fetch One Record
def search_record():
# Clear the tree first
for item in tree.get_children():
tree.delete(item)
input_id = id_entry.get()
if not input_id.isdigit():
messagebox.showwarning("Invalid Input", "Please enter a valid numeric ID.")
return
try:
cursor.execute("SELECT id, name FROM tblusers WHERE id = %s", (input_id,))
row = cursor.fetchone()
if row:
tree.insert("", "end", values=row)
else:
messagebox.showinfo("Not Found", f"No record found with ID {input_id}")
except Exception as e:
messagebox.showerror("Error", str(e))
tk.Button(search_frame, text="Search", command=search_record).pack(side=tk.LEFT, padx=5)
# --- Treeview Setup ---
tree = ttk.Treeview(root, columns=("id", "name"), show="headings")
tree.heading("id", text="ID")
tree.heading("name", text="Name")
tree.pack()
root.mainloop()
---
What to Change
Replace your_username, your_password, your_database, and your_table with your actual database info.
Adjust the columns (id, name) if your table has different fields.
****************************************
# Create a login form using Tkinter in Python, connected to a MySQL database.
1. Requirements
Make sure you have these installed:
>> pip install mysql-connector-python
2. MySQL Database Setup
Create a MySQL database and user table.
Example SQL:
CREATE DATABASE user_db;
USE user_db;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
password VARCHAR(50) NOT NULL
);
# Insert a test user:
INSERT INTO users (username, password) VALUES ('admin', 'admin123');
---
3. Python Tkinter Login Form Code
import tkinter as tk
from tkinter import messagebox
import mysql.connector
# Function to check login credentials
def login():
username = entry_user.get()
password = entry_pass.get()
if username == "" or password == "":
messagebox.showwarning("Input error", "Please fill all fields")
return
try:
# Connect to MySQL
conn = mysql.connector.connect(
host="localhost",
user="your_mysql_user",
password="your_mysql_password",
database="user_db"
)
cursor = conn.cursor()
query = "SELECT * FROM users WHERE username=%s AND password=%s"
cursor.execute(query, (username, password))
result = cursor.fetchone()
if result:
messagebox.showinfo("Login success", f"Welcome, {username}!")
else:
messagebox.showerror("Login failed", "Invalid credentials")
cursor.close()
conn.close()
except mysql.connector.Error as err:
messagebox.showerror("Database error", f"Error: {err}")
# Create the GUI window
root = tk.Tk()
root.title("Login Form")
root.geometry("300x200")
# Username
tk.Label(root, text="Username").pack(pady=5)
entry_user = tk.Entry(root)
entry_user.pack()
# Password
tk.Label(root, text="Password").pack(pady=5)
entry_pass = tk.Entry(root, show='*')
entry_pass.pack()
# Login button
tk.Button(root, text="Login", command=login).pack(pady=20)
root.mainloop()
---
4. Notes
Replace "your_mysql_user" and "your_mysql_password" with your actual MySQL credentials.
Never store plaintext passwords in a real-world application — use password hashing like bcrypt.
Would you like an enhanced version with password hashing and registration as well?
****************************************
@ IF login successful then hide Login form and show other form
To hide the login form and show another form after successful login in Tkinter,
you can destroy the login window and open a new one.
Here's how to modify the code:
---
Full Example with Second Form
import tkinter as tk
from tkinter import messagebox
import mysql.connector
def open_main_form(username):
main_form = tk.Tk()
main_form.title("Main App")
main_form.geometry("300x200")
tk.Label(main_form, text=f"Welcome, {username}!", font=("Arial", 14)).pack(pady=50)
tk.Button(main_form, text="Exit", command=main_form.destroy).pack()
main_form.mainloop()
def login():
username = entry_user.get()
password = entry_pass.get()
if username == "" or password == "":
messagebox.showwarning("Input error", "Please fill all fields")
return
try:
# Connect to MySQL
conn = mysql.connector.connect(
host="localhost",
user="root",
password="Admin@2025",
database="user_db"
)
cursor = conn.cursor()
query = "SELECT * FROM users WHERE username=%s AND password=%s"
cursor.execute(query, (username, password))
result = cursor.fetchone()
if result:
messagebox.showinfo("Login success", f"Welcome, {username}!")
login_window.destroy() # Close login window
open_main_form(username) # Open main app window
else:
messagebox.showerror("Login failed", "Invalid credentials")
cursor.close()
conn.close()
except mysql.connector.Error as err:
messagebox.showerror("Database error", f"Error: {err}")
# Create the login form
login_window = tk.Tk()
login_window.title("Login Form")
login_window.geometry("300x200")
tk.Label(login_window, text="Username").pack(pady=5)
entry_user = tk.Entry(login_window)
entry_user.pack()
tk.Label(login_window, text="Password").pack(pady=5)
entry_pass = tk.Entry(login_window, show='*')
entry_pass.pack()
tk.Button(login_window, text="Login", command=login).pack(pady=20)
login_window.mainloop()
---
What this does:
If login is successful:
The login window closes.
A new main application window opens with a welcome message.
# How to use Toplevel() to show the second form within the same main application after successful login.
This is cleaner and more appropriate than opening another Tk() window.
Tkinter Login with Toplevel() Main Form :
import tkinter as tk
from tkinter import messagebox
import mysql.connector
def open_main_form(username):
main_form = tk.Toplevel(login_window)
main_form.title("Main Application")
main_form.geometry("300x200")
tk.Label(main_form, text=f"Welcome, {username}!", font=("Arial", 14)).pack(pady=50)
tk.Button(main_form, text="Close App", command=login_window.destroy).pack()
def login():
username = entry_user.get()
password = entry_pass.get()
if username == "" or password == "":
messagebox.showwarning("Input error", "Please fill all fields")
return
try:
# Connect to MySQL
conn = mysql.connector.connect(
host="localhost",
user="root",
password="Admin@2025",
database="user_db"
)
cursor = conn.cursor()
query = "SELECT * FROM users WHERE username=%s AND password=%s"
cursor.execute(query, (username, password))
result = cursor.fetchone()
if result:
messagebox.showinfo("Login success", f"Welcome, {username}!")
# Hide login widgets
login_frame.pack_forget()
# Open new form using Toplevel
open_main_form(username)
else:
messagebox.showerror("Login failed", "Invalid credentials")
cursor.close()
conn.close()
except mysql.connector.Error as err:
messagebox.showerror("Database error", f"Error: {err}")
# Main window
login_window = tk.Tk()
login_window.title("Login Form")
login_window.geometry("300x200")
# Frame for login widgets (makes hiding easier)
login_frame = tk.Frame(login_window)
login_frame.pack(pady=20)
tk.Label(login_frame, text="Username").pack(pady=5)
entry_user = tk.Entry(login_frame)
entry_user.pack()
tk.Label(login_frame, text="Password").pack(pady=5)
entry_pass = tk.Entry(login_frame, show='*')
entry_pass.pack()
tk.Button(login_frame, text="Login", command=login).pack(pady=20)
login_window.mainloop()
---
Key Points:
Toplevel() creates a new window attached to the root (login_window).
Instead of destroying the login window, we hide the login frame using pack_forget().
This way, the app runs as a single process with multiple windows.
# Python Tkinter GUI Database App using Class
import tkinter as tk
from tkinter import ttk, messagebox
import mysql.connector
# MySQL connection
def connect_db():
try:
return mysql.connector.connect(
host="localhost",
user="your_username",
password="your_password",
database="testdb"
)
except mysql.connector.Error as err:
messagebox.showerror("Database Error", f"Error: {err}")
return None
# Main App Class
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Multi-Page Tkinter + MySQL App")
self.geometry("600x450")
self.resizable(False, False)
# Create container and all frames
container = tk.Frame(self)
container.pack(fill="both", expand=True)
self.frames = {}
for F in (LoginPage, DashboardPage, UserFormPage):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(LoginPage)
def show_frame(self, page):
frame = self.frames[page]
frame.tkraise()
# Login Page
class LoginPage(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
tk.Label(self, text="Login Page", font=("Arial", 18)).pack(pady=20)
tk.Label(self, text="Username").pack()
self.username_entry = tk.Entry(self)
self.username_entry.pack()
tk.Label(self, text="Password").pack()
self.password_entry = tk.Entry(self, show="*")
self.password_entry.pack()
tk.Button(self, text="Login", command=self.login).pack(pady=10)
def login(self):
# Just a mock login (replace with real user table if needed)
if self.username_entry.get() == "admin" and self.password_entry.get() == "admin":
self.controller.show_frame(DashboardPage)
else:
messagebox.showerror("Login Failed", "Invalid credentials.")
# Dashboard Page
class DashboardPage(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
tk.Label(self, text="Dashboard", font=("Arial", 18)).pack(pady=20)
tk.Button(self, text="Manage Users", command=lambda: controller.show_frame(UserFormPage)).pack(pady=10)
tk.Button(self, text="Logout", command=lambda: controller.show_frame(LoginPage)).pack()
# User Form Page
class UserFormPage(tk.Frame):
def __init__(self, parent, controller):
super().__init__(parent)
self.controller = controller
self.selected_id = None
tk.Label(self, text="User Form", font=("Arial", 16)).pack(pady=10)
# Entry fields
self.name_entry = tk.Entry(self, width=30)
self.email_entry = tk.Entry(self, width=30)
tk.Label(self, text="Name").pack()
self.name_entry.pack()
tk.Label(self, text="Email").pack()
self.email_entry.pack()
btn_frame = tk.Frame(self)
btn_frame.pack(pady=10)
tk.Button(btn_frame, text="Add", command=self.insert_data).grid(row=0, column=0, padx=5)
tk.Button(btn_frame, text="Update", command=self.update_data).grid(row=0, column=1, padx=5)
tk.Button(btn_frame, text="Delete", command=self.delete_data).grid(row=0, column=2, padx=5)
tk.Button(btn_frame, text="Back", command=lambda: controller.show_frame(DashboardPage)).grid(row=0, column=3, padx=5)
# Search box
self.search_entry = tk.Entry(self)
self.search_entry.pack()
tk.Button(self, text="Search", command=self.search_data).pack(pady=5)
# Treeview table
self.tree = ttk.Treeview(self, columns=("ID", "Name", "Email"), show='headings')
self.tree.heading("ID", text="ID")
self.tree.heading("Name", text="Name")
self.tree.heading("Email", text="Email")
self.tree.bind("<>", self.select_item)
self.tree.pack(fill="both", expand=True, pady=10)
self.fetch_data()
def insert_data(self):
name = self.name_entry.get()
email = self.email_entry.get()
if name and email:
conn = connect_db()
if conn:
cursor = conn.cursor()
cursor.execute("INSERT INTO users (name, email) VALUES (%s, %s)", (name, email))
conn.commit()
conn.close()
messagebox.showinfo("Success", "User added.")
self.clear()
self.fetch_data()
def fetch_data(self):
for row in self.tree.get_children():
self.tree.delete(row)
conn = connect_db()
if conn:
cursor = conn.cursor()
cursor.execute("SELECT id, name, email FROM users")
for row in cursor.fetchall():
self.tree.insert("", tk.END, values=row)
conn.close()
def select_item(self, event):
selected = self.tree.focus()
if selected:
values = self.tree.item(selected, 'values')
self.selected_id = values[0]
self.name_entry.delete(0, tk.END)
self.email_entry.delete(0, tk.END)
self.name_entry.insert(0, values[1])
self.email_entry.insert(0, values[2])
def update_data(self):
if not self.selected_id:
messagebox.showwarning("Select a record", "Please select a user to update.")
return
conn = connect_db()
if conn:
cursor = conn.cursor()
cursor.execute("UPDATE users SET name=%s, email=%s WHERE id=%s",
(self.name_entry.get(), self.email_entry.get(), self.selected_id))
conn.commit()
conn.close()
messagebox.showinfo("Updated", "User updated.")
self.clear()
self.fetch_data()
def delete_data(self):
if not self.selected_id:
messagebox.showwarning("Select a record", "Please select a user to delete.")
return
confirm = messagebox.askyesno("Confirm", "Are you sure?")
if confirm:
conn = connect_db()
if conn:
cursor = conn.cursor()
cursor.execute("DELETE FROM users WHERE id=%s", (self.selected_id,))
conn.commit()
conn.close()
messagebox.showinfo("Deleted", "User deleted.")
self.clear()
self.fetch_data()
def search_data(self):
keyword = self.search_entry.get()
for row in self.tree.get_children():
self.tree.delete(row)
conn = connect_db()
if conn:
cursor = conn.cursor()
cursor.execute("SELECT id, name, email FROM users WHERE name LIKE %s OR email LIKE %s",
('%' + keyword + '%', '%' + keyword + '%'))
for row in cursor.fetchall():
self.tree.insert("", tk.END, values=row)
conn.close()
def clear(self):
self.name_entry.delete(0, tk.END)
self.email_entry.delete(0, tk.END)
self.search_entry.delete(0, tk.END)
self.selected_id = None
# Run the app
if __name__ == "__main__":
app = App()
app.mainloop()