DEV Community

Mate Technologies
Mate Technologies

Posted on

Build a PC Usage Time Tracker in Python 🖥️⏱️

In this tutorial, we’ll build a desktop app that tracks how much time you spend on each application on your PC. It’s offline, lightweight, and beginner-friendly.

Check out the full source code here: PCUsageTimeTracker on GitHub

We’ll use:

tkinter → GUI

ttkbootstrap → modern dark/light theme for Tkinter

pygetwindow → detect active windows

psutil → optional system info

matplotlib → draw charts

Step 1: Set Up Your Project

Create a project folder and install required packages:

pip install ttkbootstrap pygetwindow psutil matplotlib
Enter fullscreen mode Exit fullscreen mode

Why these packages?

ttkbootstrap: stylish GUI

pygetwindow: track which app is active

psutil: get system info

matplotlib: visualize usage with charts

Step 2: Import Modules

Create main.py:

import tkinter as tk
from tkinter import filedialog, messagebox
import ttkbootstrap as tb
from ttkbootstrap.constants import *
import time
import json
import threading
from pathlib import Path
from datetime import datetime
import psutil
import pygetwindow as gw
import matplotlib.pyplot as plt
Enter fullscreen mode Exit fullscreen mode

These handle GUI, time, files, threading, and charting.

Step 3: Create the Main Class

class PCUsageTimeTracker:
    APP_NAME = "PC Usage Time Tracker"
    APP_VERSION = "1.0.0"

    def __init__(self):
        self.root = tk.Tk()
        tb.Style(theme="darkly")
        self.root.title(f"{self.APP_NAME} v{self.APP_VERSION}")
        self.root.geometry("1000x650")
Enter fullscreen mode Exit fullscreen mode

Explanation:

tk.Tk() → main window

tb.Style(theme="darkly") → dark theme

geometry → window size

Step 4: Set Up Data Storage

        self.app_dir = Path.home() / ".pc_usage_time_tracker"
        self.app_dir.mkdir(exist_ok=True)
        self.data_file = self.app_dir / "usage_data.json"

        self.running = True
        self.current_app = None
        self.last_switch = time.time()
        self.usage = self.load_data()
Enter fullscreen mode Exit fullscreen mode

Stores usage locally in a hidden folder.

Tracks the current app and last switch time.

Step 5: Load and Save Data

    def load_data(self):
        if self.data_file.exists():
            try:
                return json.loads(self.data_file.read_text())
            except Exception:
                return {}
        return {}

    def save_data(self):
        self.data_file.write_text(json.dumps(self.usage, indent=2))
Enter fullscreen mode Exit fullscreen mode

Loads previous usage if it exists

Saves usage in JSON format

Step 6: Detect Foreground App

    def get_foreground_app(self):
        try:
            win = gw.getActiveWindow()
            if not win:
                return "Unknown"
            return win.title or "Unknown"
        except Exception:
            return "Unknown"
Enter fullscreen mode Exit fullscreen mode

Gets the title of the active window

Returns "Unknown" if nothing is active

Step 7: Add Time to Apps

    def add_time(self, app, seconds):
        today = datetime.now().strftime("%Y-%m-%d")
        self.usage.setdefault(today, {})
        self.usage[today].setdefault(app, 0)
        self.usage[today][app] += seconds
Enter fullscreen mode Exit fullscreen mode

Tracks usage per day

Adds seconds to the current app

Step 8: Tracker Loop

    def tracker_loop(self):
        while self.running:
            app = self.get_foreground_app()
            now = time.time()

            if self.current_app is None:
                self.current_app = app
                self.last_switch = now
            elif app != self.current_app:
                delta = now - self.last_switch
                self.add_time(self.current_app, delta)
                self.current_app = app
                self.last_switch = now
                self.save_data()

            time.sleep(1)
Enter fullscreen mode Exit fullscreen mode

Runs in the background

Updates usage when the active app changes

Step 9: Build the GUI

    def _build_ui(self):
        tb.Label(self.root, text=self.APP_NAME, font=("Segoe UI", 22, "bold")).pack(pady=(10, 2))
        tb.Label(
            self.root,
            text="Offline Application Usage Tracker",
            font=("Segoe UI", 10, "italic"),
            foreground="#9ca3af"
        ).pack(pady=(0, 10))
Enter fullscreen mode Exit fullscreen mode

Adds title and subtitle

Tabs for Usage and Charts

        self.tabs = tb.Notebook(self.root)
        self.tabs.pack(fill="both", expand=True, padx=10, pady=6)

        self.tab_usage = tb.Frame(self.tabs)
        self.tab_charts = tb.Frame(self.tabs)

        self.tabs.add(self.tab_usage, text="Usage & Guide")
        self.tabs.add(self.tab_charts, text="Charts")
Enter fullscreen mode Exit fullscreen mode

Step 10: Display Usage Instructions

        self.usage_box = tk.Text(self.tab_usage)
        self.usage_box.pack(fill="both", expand=True, padx=10, pady=10)

        guide = (
            "How to use:\n\n"
            "• Leave the app running in the background.\n"
            "• It automatically tracks which application is active.\n"
            "• View today’s usage here.\n"
            "• Open Charts to see visual summaries.\n"
            "• Export data anytime.\n"
            "• Reset if you want a fresh start.\n\n"
            "Privacy:\n"
            "• No keystrokes\n"
            "• No screenshots\n"
            "• No internet\n"
            "• All data stored locally in usage_data.json\n"
        )
        self.usage_box.insert(tk.END, guide)
Enter fullscreen mode Exit fullscreen mode

Step 11: Add Buttons

        ctrl = tb.Frame(self.root)
        ctrl.pack(fill="x", padx=10, pady=10)

        tb.Button(ctrl, text="🔄 Refresh", command=self.refresh_usage).pack(side="left", padx=4)
        tb.Button(ctrl, text="💾 Export", command=self.export_data).pack(side="left", padx=4)
        tb.Button(ctrl, text="🧹 Reset", bootstyle="danger-outline", command=self.reset_data).pack(side="left", padx=4)
        tb.Button(ctrl, text="ℹ Info", bootstyle="info-outline", command=self.show_about).pack(side="right", padx=4)
Enter fullscreen mode Exit fullscreen mode

Refresh → updates usage

Export → saves JSON to a file

Reset → clears usage

Info → shows app info

Step 12: Refresh Usage

    def refresh_usage(self):
        self.usage = self.load_data()
        today = datetime.now().strftime("%Y-%m-%d")
        apps = self.usage.get(today, {})

        self.usage_box.delete("1.0", tk.END)
        self.usage_box.insert(tk.END, f"Today: {today}\n\n")

        for app, secs in sorted(apps.items(), key=lambda x: -x[1]):
            mins = int(secs // 60)
            self.usage_box.insert(tk.END, f"{app[:80]} — {mins} min\n")
Enter fullscreen mode Exit fullscreen mode

Step 13: Show Charts

    def show_today_chart(self):
        today = datetime.now().strftime("%Y-%m-%d")
        apps = self.usage.get(today, {})

        if not apps:
            messagebox.showinfo("Charts", "No data for today yet.")
            return

        labels = list(apps.keys())
        values = [v / 60 for v in apps.values()]

        plt.figure()
        plt.barh(labels, values)
        plt.title("Today's Application Usage (minutes)")
        plt.tight_layout()
        plt.show()
Enter fullscreen mode Exit fullscreen mode

Step 14: Export and Reset Data

    def export_data(self):
        path = filedialog.asksaveasfilename(defaultextension=".txt")
        if not path:
            return
        with open(path, "w", encoding="utf-8") as f:
            json.dump(self.usage, f, indent=2)
        messagebox.showinfo("Export", "Usage data exported successfully.")

    def reset_data(self):
        if messagebox.askyesno("Reset", "Clear all tracked usage?"):
            self.usage = {}
            self.save_data()
            self.refresh_usage()
Enter fullscreen mode Exit fullscreen mode

Step 15: Run the App

if __name__ == "__main__":
    tracker = PCUsageTimeTracker()
    threading.Thread(target=tracker.tracker_loop, daemon=True).start()
    tracker.run()
Enter fullscreen mode Exit fullscreen mode

✅ That’s it! You now have a fully functional PC Usage Time Tracker.

Tracks active apps automatically

Stores data locally

Shows usage and charts

Allows export and reset

You can view and clone the full project here: https://github.com/rogers-cyber/PCUsageTimeTracker

Top comments (0)