DEV Community

Mate Technologies
Mate Technologies

Posted on

🌤️ Build Your Own AI-Powered Weather Prediction App with Python

In this tutorial, we’ll build WeatherSentinel v1.0, a Python app that predicts weather for any location. We’ll use Tkinter for the GUI and ttkbootstrap for styling. By the end, you’ll have a working weather forecasting app!

Step 1: Set Up Your Project

Make a new folder for your project:

mkdir weather-sentinel
cd weather-sentinel
Enter fullscreen mode Exit fullscreen mode

Install the dependencies:

pip install ttkbootstrap
Enter fullscreen mode Exit fullscreen mode

Tip: ttkbootstrap gives Tkinter a modern look without complicated styling.

Step 2: Import Required Libraries

Start by importing Python libraries for GUI, threading, and random data (we’ll simulate weather forecasts here).

import os
import sys
import threading
import time
import random
import tkinter as tk
from tkinter import messagebox, ttk
import ttkbootstrap as tb
from ttkbootstrap.constants import *
Enter fullscreen mode Exit fullscreen mode

Why threading?
We use threads so the UI doesn’t freeze while predictions run in the background.

Step 3: Resource Helper

Add a helper function to load files (like icons) reliably:

def resource_path(file_name):
    base_path = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, file_name)
Enter fullscreen mode Exit fullscreen mode

This ensures your app can find files whether running as a script or an executable.

Step 4: Weather Worker Class

This class simulates fetching weather forecasts for a given location and number of days.

class WeatherWorker:
    def __init__(self, location, days, callbacks):
        self.location = location
        self.days = days
        self.callbacks = callbacks
        self._running = True

    def stop(self):
        self._running = False

    def run(self):
        forecasts = []
        conditions = ["Sunny", "Cloudy", "Rain", "Storm", "Snow", "Fog"]

        for day in range(1, self.days + 1):
            if not self._running:
                break
            time.sleep(0.5)  # simulate API delay
            forecast = {
                "day": f"Day {day}",
                "temp": random.randint(-5, 35),
                "humidity": random.randint(30, 90),
                "condition": random.choice(conditions)
            }
            forecasts.append(forecast)

            # Update UI
            if "progress" in self.callbacks:
                self.callbacks["progress"](int(day / self.days * 100))
            if "update" in self.callbacks:
                self.callbacks["update"](forecast)

        if "finished" in self.callbacks:
            self.callbacks["finished"](forecasts)
Enter fullscreen mode Exit fullscreen mode

Beginner Tip: Callbacks allow this class to communicate with the GUI without directly modifying it.

Step 5: Create the Main App GUI

We’ll build the interface using ttkbootstrap.

class WeatherSentinelApp:
    APP_NAME = "WeatherSentinel"
    APP_VERSION = "1.0"

    def __init__(self):
        self.root = tb.Window(themename="darkly")
        self.root.title(f"{self.APP_NAME} v{self.APP_VERSION}")
        self.root.minsize(900, 550)
        self.worker = None
        self._build_ui()
Enter fullscreen mode Exit fullscreen mode

Step 5a: Build the UI Layout

def _build_ui(self):
    main = tb.Frame(self.root, padding=12)
    main.pack(fill=tk.BOTH, expand=True)

    tb.Label(main, text=f"🌤️ {self.APP_NAME} - Weather Prediction System",
             font=("Segoe UI", 22, "bold")).pack(pady=(0, 5))

    tb.Label(main, text="Location-based weather forecasting with predictive insights",
             font=("Segoe UI", 10, "italic"), foreground="#9ca3af").pack(pady=(0, 20))
Enter fullscreen mode Exit fullscreen mode

Pro Tip: Use frames to organize the UI and keep it neat.

Step 5b: Add Controls (Input Fields & Buttons)

controls = tb.Frame(main)
controls.pack(fill=tk.X, pady=(0, 10))

tb.Label(controls, text="Location").pack(side=tk.LEFT, padx=5)
self.location_entry = tb.Entry(controls, width=30)
self.location_entry.pack(side=tk.LEFT, padx=5)
self.location_entry.insert(0, "New York")

tb.Label(controls, text="Forecast Days").pack(side=tk.LEFT, padx=5)
self.days_combo = tb.Combobox(controls, values=[1, 3, 5, 7], width=5)
self.days_combo.set(5)
self.days_combo.pack(side=tk.LEFT, padx=5)

self.start_btn = tb.Button(controls, text="🔍 Predict", bootstyle=SUCCESS, command=self.start)
self.start_btn.pack(side=tk.LEFT, padx=5)

self.cancel_btn = tb.Button(controls, text="⏹ Cancel", bootstyle=DANGER, command=self.cancel)
self.cancel_btn.pack(side=tk.LEFT, padx=5)
self.cancel_btn.config(state=tk.DISABLED)
Enter fullscreen mode Exit fullscreen mode

Why combobox for days?
It limits users to valid forecast lengths (1, 3, 5, or 7 days).

Step 5c: Add Progress Bar & Table

self.progress = tb.Progressbar(main, bootstyle="info-striped", maximum=100)
self.progress.pack(fill=tk.X, pady=(0, 10))

columns = ("day", "temp", "humidity", "condition")
self.tree = ttk.Treeview(main, columns=columns, show="headings", height=15)
for col in columns:
    self.tree.heading(col, text=col.capitalize())
    self.tree.column(col, anchor=tk.CENTER)
self.tree.pack(fill=tk.BOTH, expand=True)
Enter fullscreen mode Exit fullscreen mode

Beginner Tip: Treeview is perfect for displaying tabular data like forecasts.

Step 6: Add Actions (Start & Cancel)

def start(self):
    location = self.location_entry.get().strip()
    if not location:
        messagebox.showwarning("Input Required", "Please enter a location")
        return

    self.tree.delete(*self.tree.get_children())
    self.progress["value"] = 0
    self.start_btn.config(state=tk.DISABLED)
    self.cancel_btn.config(state=tk.NORMAL)
    self.status_label.config(text="Predicting weather...")

    self.worker = WeatherWorker(
        location=location,
        days=int(self.days_combo.get()),
        callbacks={
            "progress": self.set_progress,
            "update": self.add_forecast,
            "finished": self.finish
        }
    )
    threading.Thread(target=self.worker.run, daemon=True).start()

def cancel(self):
    if self.worker:
        self.worker.stop()
    self.finish([])
Enter fullscreen mode Exit fullscreen mode

Step 6a: Update Progress & Table

def add_forecast(self, data):
    self.tree.insert("", tk.END,
                     values=(data["day"], f"{data['temp']} °C", f"{data['humidity']} %", data["condition"]))

def set_progress(self, value):
    self.progress["value"] = value

def finish(self, forecasts):
    self.start_btn.config(state=tk.NORMAL)
    self.cancel_btn.config(state=tk.DISABLED)
    self.status_label.config(text=f"Forecast completed ({len(forecasts)} days)")

Enter fullscreen mode Exit fullscreen mode

Step 7: Run the App

if __name__ == "__main__":
    app = WeatherSentinelApp()
    app.run()
Enter fullscreen mode Exit fullscreen mode

Run the script:

python weather_sentinel.py

You now have a fully working weather prediction app with a clean, modern UI! 🎉

✅ Optional Improvements

Connect to a real weather API like OpenWeatherMap.

Save forecasts to a file (CSV/JSON).

Add charts for visualizing temperature trends.

Get the Full Code

Clone the GitHub repo directly:
https://github.com/rogers-cyber/python-tiny-tools/tree/main/Weather-prediction-app

Top comments (0)