Friday, June 12, 2026

How to Build a Graphical Windows Task Manager Using Python and Tkinter

Command-line performance tools are incredibly efficient, but sometimes you or your helpdesk users need a clean, interactive user interface. Building a custom graphical utility allows you to monitor critical resources without crowding your desktop workspace with heavy applications.

We can transform our process tracking engine into a standalone desktop application using Python's built-in tkinter graphical library. By binding our data collection functions to an automated structural interface window, we create a real-time tracking panel complete with single-click process termination controls.

Here is the complete HTML framework and GUI desktop script ready for your next Blogger update.


📦 Step 1: Verify Requirements

This desktop utility relies on tkinter for the interface framework and psutil for retrieving hardware performance statistics. If you haven't installed the metrics collector yet, open your console and run:

pip install psutil

🐍 The Python Tkinter Task Manager Script

This script sets up a graphical layout containing general usage bars, a structured process viewing list, and an operational button mechanism. Save this source layout code as gui_task_manager.py:

import tkinter as tk
from tkinter import ttk, messagebox
import psutil

class TaskManagerGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("Ayouli IT Tech: Performance Monitor")
        self.root.geometry("650x450")
        self.root.minsize(550, 350)

        # Top Control Frame for global usage readouts
        self.stats_frame = ttk.LabelFrame(root, text=" Global Hardware Utilization ", padding=10)
        self.stats_frame.pack(fill="x", padx=10, pady=5)

        self.cpu_label = ttk.Label(self.stats_frame, text="CPU Usage: 0%", font=("Arial", 10, "bold"))
        self.cpu_label.pack(side="left", padx=20)

        self.ram_label = ttk.Label(self.stats_frame, text="RAM Usage: 0%", font=("Arial", 10, "bold"))
        self.ram_label.pack(side="left", padx=20)

        # Central Process List Frame
        self.list_frame = ttk.Frame(root, padding=10)
        self.list_frame.pack(fill="both", expand=True)

        # Create structured treeview layout grid columns
        columns = ("pid", "name", "cpu", "ram")
        self.tree = ttk.Treeview(self.list_frame, columns=columns, show="headings", selectmode="browse")
        
        self.tree.heading("pid", text="PID")
        self.tree.heading("name", text="Process Name")
        self.tree.heading("cpu", text="CPU %")
        self.tree.heading("ram", text="RAM %")

        self.tree.column("pid", width=70, anchor="center")
        self.tree.column("name", width=250, anchor="w")
        self.tree.column("cpu", width=80, anchor="center")
        self.tree.column("ram", width=80, anchor="center")

        # Scrollbar binding integration
        scrollbar = ttk.Scrollbar(self.list_frame, orient="vertical", command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        self.tree.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

        # Bottom Functional Control Area
        self.action_frame = ttk.Frame(root, padding=10)
        self.action_frame.pack(fill="x")

        self.kill_button = ttk.Button(self.action_frame, text="End Task Process", command=self.kill_process)
        self.kill_button.pack(side="right", padx=10)

        # Initialize the looping live update loop engine
        self.update_metrics()

    def update_metrics(self):
        """Fetches live machine state changes and refreshes window lists."""
        # Update global metric string panels
        cpu_percent = psutil.cpu_percent()
        ram_percent = psutil.virtual_memory().percent
        
        self.cpu_label.config(text=f"CPU Usage: {cpu_percent}%")
        self.ram_label.config(text=f"RAM Usage: {ram_percent}%")

        # Preserve the user choice configuration during data redraw routines
        selected_item = self.tree.selection()
        selected_pid = None
        if selected_item:
            selected_pid = self.tree.item(selected_item[0])['values'][0]

        # Flush current item entries to write fresh records
        for item in self.tree.get_children():
            self.tree.delete(item)

        # Pull system processes lists safely
        processes = []
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            try:
                processes.append(proc.info)
            except (psutil.NoSuchProcess, psutil.AccessDenied):
                continue

        # Sort the rows dynamically based on the highest RAM footprint
        sorted_processes = sorted(processes, key=lambda x: x['memory_percent'] or 0, reverse=True)

        # Inject matching system elements into the active layout tree
        for p in sorted_processes[:25]: # Restrict view grid depth to top 25 records
            item_id = self.tree.insert("", "end", values=(
                p['pid'], 
                p['name'], 
                f"{p['cpu_percent']:.1f}", 
                f"{p['memory_percent']:.1f}"
            ))
            # Restore selection highlighting state matches smoothly
            if selected_pid and p['pid'] == selected_pid:
                self.tree.selection_set(item_id)

        # Schedule the next screen redraw tracking sweep to run in 2000ms (2 seconds)
        self.root.after(2000, self.update_metrics)

    def kill_process(self):
        """Targets a selected process id entry point and drops execution calls."""
        selected_item = self.tree.selection()
        if not selected_item:
            messagebox.showwarning("Selection Missing", "Please select a specific process from the tracking grid.")
            return

        pid, name, _, _ = self.tree.item(selected_item[0])['values']
        
        confirm = messagebox.askyesno("Confirm Action", f"Are you sure you want to terminate {name} (PID: {pid})?")
        if confirm:
            try:
                process = psutil.Process(pid)
                process.terminate() # Fire termination request sequence signal 
                messagebox.showinfo("Task Dropped", f"Process {name} terminated successfully.")
            except psutil.AccessDenied:
                messagebox.showerror("Access Denied", "Insufficient security context to drop this system application.")
            except psutil.NoSuchProcess:
                messagebox.showerror("Error", "The chosen process has already exited or changed state paths.")

if __name__ == "__main__":
    app_root = tk.Tk()
    manager = TaskManagerGUI(app_root)
    app_root.mainloop()

⚙️ Step-by-Step UI Execution Instructions

1. Run the Interface Window

Launch the Python application inside your target system directory via your typical terminal launcher context:

python gui_task_manager.py

2. Admin Elevation Constraints

If you launch the monitor tool inside a standard user context environment, you can view background activities safely. However, attempting to close core protected Windows items via the End Task Process button will return an Access Denied structural alert. To interact with high-privilege apps, run your original CMD shell launcher as an **Administrator** before executing the file.

No comments:

Post a Comment