Build an Interactive Iris Flower Classifier GUI with Python

Published: (January 18, 2026 at 08:30 PM EST)
4 min read
Source: Dev.to

Source: Dev.to

What we’ll use

  • scikit‑learn – machine learning
  • pandas – CSV handling
  • tkinter + ttkbootstrap – GUI
  • Optional: tkinterdnd2 – drag & drop support

You can clone the full repository here:

🔗 Iris-Flower-Classifier-GUI on GitHub

Install dependencies

pip install pandas scikit-learn ttkbootstrap
# Optional: for drag & drop
pip install tkinterdnd2

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

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")

Here we import:

  • pandas for handling CSV files
  • tkinter & ttkbootstrap for modern GUI elements
  • tkinterdnd2 if you want drag‑&‑drop CSV support

Create the Iris machine‑learning model

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]

Explanation

  • Features are standardized for better model performance.
  • A Random Forest classifier is beginner‑friendly and works well for this classification task.

Worker for CSV processing

This worker lets the GUI handle multiple CSV files without freezing the interface.

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)
                required = {"sepal_length", "sepal_width", "petal_length", "petal_width"}
                if set(df.columns) >= required:
                    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)
                else:
                    if "found" in self.callbacks:
                        self.callbacks["found"](file, ["Error: Missing required columns"])
            except Exception as e:
                if "found" in self.callbacks:
                    self.callbacks["found"](file, [f"Error: {str(e)}"])
            # Progress update
            if "progress" in self.callbacks:
                self.callbacks["progress"](int((i + 1) / total * 100))
        # Finished
        if "finished" in self.callbacks:
            self.callbacks["finished"]()

Explanation

  • Reads CSV files one by one.
  • Predicts species using the Iris model.
  • Sends progress updates to the GUI asynchronously.

Build the GUI

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()
  • Checks if drag‑&‑drop is available.
  • Initializes ttkbootstrap for a modern dark 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 row
    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…")

Explanation

  • Creates an input box for file paths.
  • Adds a clear, friendly label.

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=10)
  • Browse – opens a file‑dialog.
  • Classify CSV – starts the worker thread.
  • Cancel – stops processing.
  • A progress bar visualises the classification progress.

(The remaining methods – browse, start, cancel, _apply_styles, etc. – are implemented in the original repository. They handle file selection, thread management, and UI updates.)

Run the application

if __name__ == "__main__":
    app = IrisClassifierApp()
    app.root.mainloop()

That’s it! Drop or browse CSV files containing the four Iris measurements, hit Classify, and watch the predictions appear without freezing the interface. Enjoy experimenting with machine learning and GUI development!

GUI Controls

Browse: Select CSVs

Classify CSV: Start predictions

Cancel: Stop predictions

Progress bar: Visual feedback

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")

Explanation

  • Users can manually enter flower measurements.
  • Click Predict to get the species immediately.

Run the App (alternative entry)

if __name__ == "__main__":
    app = IrisClassifierApp()
    app.run()

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

Optional Features

  • Drag & Drop CSVs (requires tkinterdnd2)
  • Export results to a 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

Iris Flower Classifier GUI

Back to Blog

Related posts

Read more »

Rapg: TUI-based Secret Manager

We've all been there. You join a new project, and the first thing you hear is: > 'Check the pinned message in Slack for the .env file.' Or you have several .env...

Technology is an Enabler, not a Saviour

Why clarity of thinking matters more than the tools you use Technology is often treated as a magic switch—flip it on, and everything improves. New software, pl...