In this tutorial, we will use ttkbootstrap meters along with psutil to display real-time system performance, including:
The psutil (python system and process utilities) library in Python provides an interface for retrieving system information, such as CPU usage, memory consumption, disk usage, network statistics, and running processes. It is widely used for system monitoring, performance analysis, and resource management in applications.
Visit Documentation# Install required libraries if not already installed
pip install ttkbootstrap psutil
# Import necessary libraries
import psutil
import ttkbootstrap as tb
import time, threading
# Function to assign colors based on usage levels
def get_bootstyle(value):
if value <= 30:
return "success"
elif value <= 70:
return "warning"
else:
return "danger"
# Create main application window
root = tb.Window(themename="superhero")
root.title("System Performance Monitor")
def update_meter():
while True:
cpu_usage = psutil.cpu_percent(interval=1)
meter.configure(amountused=cpu_usage, bootstyle=get_bootstyle(cpu_usage))
root.update_idletasks()
time.sleep(1)
# Creating the CPU usage meter
meter = tb.Meter(
root, bootstyle="success", subtext="CPU Usage", amounttotal=100, interactive=False
)
meter.pack(pady=20)
# Run the update function in a separate thread
threading.Thread(target=update_meter, daemon=True).start()
import psutil
import ttkbootstrap as tb
import time
import threading
def get_bootstyle(value):
if value <= 30:
return "success"
elif value <= 70:
return "warning"
else:
return "danger"
def update_meter():
while True:
cpu_usage = psutil.cpu_percent(interval=1)
meter.configure(amountused=cpu_usage, bootstyle=get_bootstyle(cpu_usage))
root.update_idletasks()
time.sleep(1)
root = tb.Window(themename="superhero")
root.title("CPU Usage Monitor")
meter = tb.Meter(
root, bootstyle="success", subtext="CPU Usage", amounttotal=100, interactive=False
)
meter.pack(pady=20)
threading.Thread(target=update_meter, daemon=True).start()
root.mainloop()
def update_ram_meter():
while True:
ram_usage = psutil.virtual_memory().percent
ram_meter.configure(amountused=ram_usage, bootstyle=get_bootstyle(ram_usage))
root.update_idletasks()
time.sleep(1)
# Creating the RAM usage meter
ram_meter = tb.Meter(
root, bootstyle="success", subtext="RAM Usage", amounttotal=100, interactive=False
)
ram_meter.pack(pady=20)
# Run the RAM update function in a separate thread
threading.Thread(target=update_ram_meter, daemon=True).start()
import psutil
import ttkbootstrap as tb
import time
import threading
def get_bootstyle(value):
if value <= 30:
return "success"
elif value <= 70:
return "warning"
else:
return "danger"
def update_meter():
while True:
ram_usage = psutil.virtual_memory().percent
meter.configure(amountused=ram_usage, bootstyle=get_bootstyle(ram_usage))
root.update_idletasks()
time.sleep(1)
root = tb.Window(themename="flatly")
root.title("RAM Usage Monitor")
meter = tb.Meter(
root, bootstyle="success", subtext="RAM Usage", amounttotal=100, interactive=False
)
meter.pack(pady=20)
threading.Thread(target=update_meter, daemon=True).start()
root.mainloop()
def update_disk_meter():
while True:
disk_usage = psutil.disk_usage('/').percent
disk_meter.configure(amountused=disk_usage, bootstyle=get_bootstyle(disk_usage))
root.update_idletasks()
time.sleep(2)
# Creating the Disk usage meter
disk_meter = tb.Meter(
root, bootstyle="success", subtext="Disk Usage", amounttotal=100, interactive=False
)
disk_meter.pack(pady=20)
# Run the Disk update function in a separate thread
threading.Thread(target=update_disk_meter, daemon=True).start()
import psutil
import ttkbootstrap as tb
import time
import threading
def get_bootstyle(value):
if value <= 30:
return "success"
elif value <= 70:
return "warning"
else:
return "danger"
def update_disk_meter():
while True:
disk_usage = psutil.disk_usage('/').percent
meter.configure(amountused=disk_usage, bootstyle=get_bootstyle(disk_usage))
root.update_idletasks()
time.sleep(2)
root = tb.Window(themename="solar")
root.title("Disk Usage Monitor")
meter = tb.Meter(
root, bootstyle="success", subtext="Disk Usage", amounttotal=100, interactive=False
)
meter.pack(pady=20)
threading.Thread(target=update_disck_meter, daemon=True).start()
root.mainloop()
def update_meter():
old_value = psutil.net_io_counters().bytes_recv
while True:
new_value = psutil.net_io_counters().bytes_recv
speed = (new_value - old_value) / 1024 # Convert bytes to KB/s
speed = round(speed, 2) # Format to 2 decimal places
old_value = new_value
meter.configure(amountused=min(speed, 100),
subtext=f"Speed: {speed} KB/s",
bootstyle=get_bootstyle(min(speed, 100)))
root.update_idletasks()
time.sleep(1)
# Creating the Network speed meter
network_meter = tb.Meter(
root, bootstyle="success", subtext="Download Speed (KB/s)", amounttotal=100, interactive=False
)
network_meter.pack(pady=20)
# Run the Network update function in a separate thread
threading.Thread(target=update_network_meter, daemon=True).start()
import psutil
import ttkbootstrap as tb
import time
import threading
def get_bootstyle(value):
if value <= 30:
return "success"
elif value <= 70:
return "warning"
else:
return "danger"
def update_network_meter():
old_value = psutil.net_io_counters().bytes_recv
while True:
new_value = psutil.net_io_counters().bytes_recv
speed = (new_value - old_value) / 1024 # KB/s
speed = round(speed, 2) # Format to 2 decimal places
old_value = new_value
meter.configure(amountused=min(speed, 100), bootstyle=get_bootstyle(min(speed, 100)))
root.update_idletasks()
time.sleep(1)
root = tb.Window(themename="darkly")
root.title("Network Speed Monitor")
meter = tb.Meter(
root, bootstyle="success", subtext="Download Speed (KB/s)", amounttotal=100, interactive=False
)
meter.pack(pady=20)
threading.Thread(target=update_network_meter, daemon=True).start()
root.mainloop()
def update_battery_meter():
while True:
battery = psutil.sensors_battery()
if battery:
battery_percent = battery.percent
battery_meter.configure(amountused=battery_percent, bootstyle=get_bootstyle(battery_percent))
root.update_idletasks()
time.sleep(10) # Update every 10 seconds
# Creating the Battery percentage meter
battery_meter = tb.Meter(
root, bootstyle="success", subtext="Battery Level", amounttotal=100, interactive=False
)
battery_meter.pack(pady=20)
# Run the Battery update function in a separate thread
threading.Thread(target=update_battery_meter, daemon=True).start()
import psutil
import ttkbootstrap as tb
import time
import threading
def get_bootstyle(value):
if value >= 70:
return "success"
elif value >= 30:
return "warning"
else:
return "danger"
def update_battery_meter():
while True:
battery = psutil.sensors_battery()
if battery:
percent = battery.percent
meter.configure(amountused=percent, bootstyle=get_bootstyle(percent))
root.update_idletasks()
time.sleep(10)
root = tb.Window(themename="minty")
root.title("Battery Monitor")
meter = tb.Meter(
root, bootstyle="success", subtext="Battery Level", amounttotal=100, interactive=False
)
meter.pack(pady=20)
threading.Thread(target=update_battery_meter, daemon=True).start()
root.mainloop()
root.mainloop()
This final integrated application efficiently combines all five process parameters into a single interface while maintaining a consistent look and feel. Here’s how:
This structured approach improves readability, performance, and user experience, making the app more efficient and visually appealing.
import psutil
import ttkbootstrap as tb
import time
import threading
# Function to assign bootstyle color based on usage levels
def get_bootstyle(value):
if value <= 30:
return "success"
elif value <= 70:
return "warning"
else:
return "danger"
# Function to update CPU meter
def update_cpu_meter():
while True:
cpu_usage = psutil.cpu_percent(interval=1)
cpu_meter.configure(amountused=cpu_usage, bootstyle=get_bootstyle(cpu_usage))
root.update_idletasks()
time.sleep(1)
# Function to update RAM meter
def update_ram_meter():
while True:
ram_usage = psutil.virtual_memory().percent
ram_meter.configure(amountused=ram_usage, bootstyle=get_bootstyle(ram_usage))
root.update_idletasks()
time.sleep(1)
# Function to update Disk meter
def update_disk_meter():
while True:
disk_usage = psutil.disk_usage('/').percent
disk_meter.configure(amountused=disk_usage, bootstyle=get_bootstyle(disk_usage))
root.update_idletasks()
time.sleep(2)
# Function to update Network Speed meter
def update_network_meter():
old_value = psutil.net_io_counters().bytes_recv
while True:
new_value = psutil.net_io_counters().bytes_recv
speed = (new_value - old_value) / 1024 # Convert to KB/s
speed = round(speed, 2) # Format to 2 decimal places
old_value = new_value
network_meter.configure(amountused=min(speed, 100), subtext=f"Speed: {speed} KB/s", bootstyle=get_bootstyle(speed))
root.update_idletasks()
time.sleep(1)
# Function to update Battery meter
def update_battery_meter():
while True:
battery = psutil.sensors_battery()
if battery:
battery_percent = battery.percent
battery_meter.configure(amountused=battery_percent, bootstyle=get_bootstyle(battery_percent))
root.update_idletasks()
time.sleep(10)
# Creating the main Tkinter window
root = tb.Window(themename="superhero")
root.title("System Performance Monitor")
# Configure grid layout
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
# Headline at the top right
headline = tb.Label(root, text="🔹 System Performance Monitor 🔹", font=("Arial", 16, "bold"), bootstyle="primary")
headline.grid(row=0, column=0, columnspan=2, sticky="e", padx=20, pady=10)
# Row 1: CPU & RAM
cpu_meter = tb.Meter(root, bootstyle="success", subtext="CPU Usage", amounttotal=100, interactive=False)
cpu_meter.grid(row=1, column=0, padx=20, pady=20)
ram_meter = tb.Meter(root, bootstyle="success", subtext="RAM Usage", amounttotal=100, interactive=False)
ram_meter.grid(row=1, column=1, padx=20, pady=20)
# Row 2: Disk & Network Speed
disk_meter = tb.Meter(root, bootstyle="success", subtext="Disk Usage", amounttotal=100, interactive=False)
disk_meter.grid(row=2, column=0, padx=20, pady=20)
network_meter = tb.Meter(root, bootstyle="success", subtext="Download Speed (KB/s)", amounttotal=100, interactive=False)
network_meter.grid(row=2, column=1, padx=20, pady=20)
# Row 3: Battery (Centered across two columns)
battery_meter = tb.Meter(root, bootstyle="success", subtext="Battery Level", amounttotal=100, interactive=False)
battery_meter.grid(row=3, column=0, columnspan=2, padx=20, pady=20)
# Running each function in a separate thread
threading.Thread(target=update_cpu_meter, daemon=True).start()
threading.Thread(target=update_ram_meter, daemon=True).start()
threading.Thread(target=update_disk_meter, daemon=True).start()
threading.Thread(target=update_network_meter, daemon=True).start()
threading.Thread(target=update_battery_meter, daemon=True).start()
# Running the Tkinter event loop
root.mainloop()
Threading plays a crucial role in ensuring that the application's UI remains responsive while fetching system performance data. Without threading, the main Tkinter loop would be blocked during data retrieval, causing the interface to freeze or lag. To truly understand its impact, try removing the threading implementation and observe how the app responds. You’ll notice a significant difference in performance and responsiveness.
More about ThreadingWith `psutil` and `ttkbootstrap`, we can create visually appealing and real-time system monitoring tools in Python.