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
Install the dependencies:
pip install ttkbootstrap
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 *
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)
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)
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()
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))
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)
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)
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([])
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)")
Step 7: Run the App
if __name__ == "__main__":
app = WeatherSentinelApp()
app.run()
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)