DEV Community

Mate Technologies
Mate Technologies

Posted on

Build an Interactive Iris Flower Classifier GUI with Python

Learn how to classify Iris flowers using a Random Forest model in Python with a user-friendly GUI. Perfect for beginners exploring machine learning and Python GUI development!

We’ll use:

scikit-learn for machine learning

pandas for CSV handling

tkinter + ttkbootstrap for GUI

Optional: tkinterdnd2 for drag & drop

You can clone the full repo here:
🔗 Iris-Flower-Classifier-GUI on GitHub

  1. Install Dependencies

We’ll need several Python packages. Run:

pip install pandas scikit-learn ttkbootstrap
# Optional: for drag & drop
pip install tkinterdnd2
Enter fullscreen mode Exit fullscreen mode

Note: tkinter comes pre-installed with Python on most systems.

  1. Import Libraries
import os, sys, threading
import pandas as pd
import tkinter as tk
from tkinter import filedialog, messagebox, ttk

import ttkbootstrap as tb
from ttkbootstrap.constants import *

# Optional drag & drop
try:
    from tkinterdnd2 import TkinterDnD, DND_FILES
    DND_ENABLED = True
except ImportError:
    DND_ENABLED = False
    print("Drag & Drop requires tkinterdnd2: pip install tkinterdnd2")
Enter fullscreen mode Exit fullscreen mode

Here we import:

pandas for handling CSV files

tkinter & ttkbootstrap for GUI elements

tkinterdnd2 if you want drag & drop CSV support

  1. Create the Iris Machine Learning Model

We’ll use scikit-learn’s built-in Iris dataset and a Random Forest classifier.

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

class IrisModel:
    def __init__(self):
        data = load_iris()
        self.X = data.data
        self.y = data.target
        self.target_names = data.target_names
        self.scaler = StandardScaler()

        # Scale features
        X_scaled = self.scaler.fit_transform(self.X)

        # Train/test split
        X_train, X_test, y_train, y_test = train_test_split(
            X_scaled, self.y, test_size=0.2, random_state=42
        )

        # Random Forest classifier
        self.clf = RandomForestClassifier(n_estimators=100, random_state=42)
        self.clf.fit(X_train, y_train)

    def predict(self, X):
        X_scaled = self.scaler.transform(X)
        preds = self.clf.predict(X_scaled)
        return [self.target_names[p] for p in preds]
Enter fullscreen mode Exit fullscreen mode

✅ Explanation:

Standardize input features so the model performs better.

Random Forest handles classification tasks well and is beginner-friendly.

  1. Create a Worker for CSV Processing

This will let our GUI handle multiple CSV files without freezing.

class ClassifierWorker:
    def __init__(self, files, callbacks):
        self.files = files
        self.callbacks = callbacks
        self._running = True
        self.model = IrisModel()

    def stop(self):
        self._running = False

    def run(self):
        total = len(self.files)
        for i, file in enumerate(self.files):
            if not self._running:
                break
            try:
                df = pd.read_csv(file)
                if set(df.columns) >= {"sepal_length","sepal_width","petal_length","petal_width"}:
                    X = df[["sepal_length","sepal_width","petal_length","petal_width"]].values
                    preds = self.model.predict(X)
                    if "found" in self.callbacks:
                        self.callbacks["found"](file, preds)
            except Exception as e:
                if "found" in self.callbacks:
                    self.callbacks["found"](file, [f"Error: {str(e)}"])
            if "progress" in self.callbacks:
                self.callbacks["progress"](int((i+1)/total*100))
        if "finished" in self.callbacks:
            self.callbacks["finished"]()
Enter fullscreen mode Exit fullscreen mode

✅ Explanation:

Reads CSVs one by one

Predicts species using the Iris model

Updates GUI progress asynchronously

  1. Build the GUI

We’ll create a main application class:

class IrisClassifierApp:
    def __init__(self):
        if DND_ENABLED:
            self.root = TkinterDnD.Tk()
        else:
            self.root = tb.Window(themename="darkly")
        self.root.title("IrisClassifier v1.1")
        self.root.minsize(1000, 700)
        self.worker_obj = None
        self.file_set = set()
        self.model = IrisModel()

        self._build_ui()
        self._apply_styles()
Enter fullscreen mode Exit fullscreen mode

We check if drag & drop is available

We initialize ttkbootstrap for a modern theme

GUI Layout

def _build_ui(self):
    main = tb.Frame(self.root, padding=10)
    main.pack(fill="both", expand=True)

    tb.Label(main, text="🌸 Iris Flower Classifier",
             font=("Segoe UI", 20, "bold")).pack(pady=(0,10))

    # File selection
    row1 = tb.Frame(main)
    row1.pack(fill="x", pady=(0,6))
    self.path_input = tb.Entry(row1, width=80)
    self.path_input.pack(side="left", fill="x", expand=True, padx=(0,6))
    self.path_input.insert(0, "Drag & drop CSV files here…")
Enter fullscreen mode Exit fullscreen mode

✅ Explanation:

We create an input box for file paths

Add labels for clarity

  1. Add Buttons & Progress Bar
browse_btn = tb.Button(row1, text="📂 Browse", bootstyle="info", command=self.browse)
browse_btn.pack(side="left", padx=3)

self.start_btn = tb.Button(row1, text="🚀 Classify CSV", bootstyle="success", command=self.start)
self.start_btn.pack(side="left", padx=3)

self.cancel_btn = tb.Button(row1, text="⏹ Cancel", bootstyle="danger", command=self.cancel)
self.cancel_btn.pack(side="left", padx=3)
self.cancel_btn.config(state="disabled")

self.progress = tb.Progressbar(main, bootstyle="success-striped", maximum=100)
self.progress.pack(fill="x", pady=(0,6))
Enter fullscreen mode Exit fullscreen mode

Browse: Select CSVs

Classify CSV: Start predictions

Cancel: Stop predictions

Progress bar: Visual feedback

  1. Add Manual Input
manual_frame = tb.Labelframe(main, text="Manual Input", padding=10)
manual_frame.pack(fill="x", pady=(10,6))

labels = ["Sepal Length","Sepal Width","Petal Length","Petal Width"]
self.manual_entries = {}
for i, label in enumerate(labels):
    tb.Label(manual_frame, text=label).grid(row=0, column=i*2, sticky="w")
    entry = tb.Entry(manual_frame, width=8)
    entry.grid(row=0, column=i*2+1)
    entry.insert(0, "0")
    self.manual_entries[label] = entry

predict_btn = tb.Button(manual_frame, text="🔮 Predict", bootstyle="info", command=self.manual_predict)
predict_btn.grid(row=0, column=8, padx=10)

self.manual_result = tb.Label(manual_frame, text="Prediction: ---", font=("Segoe UI", 12, "bold"))
self.manual_result.grid(row=1, column=0, columnspan=9, pady=(6,0), sticky="w")
Enter fullscreen mode Exit fullscreen mode

✅ Explanation:

Users can manually enter flower measurements

Click Predict to get the species immediately

  1. Run the App
if __name__ == "__main__":
    app = IrisClassifierApp()
    app.run()

Enter fullscreen mode Exit fullscreen mode

And that’s it! Your interactive Iris Flower Classifier is ready to run.

  1. Optional Features

Drag & Drop CSVs (requires tkinterdnd2)

Export Results to text file

Beautiful dark/light theme with ttkbootstrap

🎯 Summary

You’ve learned how to:

Train a Random Forest classifier on the Iris dataset

Build a Python GUI to interact with it

Load CSV files and make manual predictions

Visualize progress and results

Check out the full project here:
🔗 Iris-Flower-Classifier-GUI on GitHub

Top comments (0)