DEV Community

Mate Technologies
Mate Technologies

Posted on

🧠📖 Build a Beginner-Friendly AI‑Assisted Story Generator with Python & Tkinter

This step‑by‑step Dev.to tutorial walks you through building a desktop story generator app using Python + Tkinter.

We’ll start small, explain every piece, and gradually assemble the full app—so even if Tkinter feels scary, you’ll be comfortable by the end.

✅ What You’ll Build

A clean Tkinter GUI

Light/Dark theme toggle

AI‑style story generation (rule‑based, no API)

Story history vault

Typing animation for story playback

Export stories to a .txt file

🧩 Prerequisites

Python 3.9+

Basic Python knowledge (functions, lists, strings)

Install Required Package
pip install sv-ttk
1️⃣ Imports & Project Setup

We begin by importing everything we’ll need.

import sys
import os
import threading
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import sv_ttk
import random
import time
Enter fullscreen mode Exit fullscreen mode

🔍 What These Do
Module Purpose
tkinter GUI framework
ttk Modern widgets
sv_ttk Light/Dark themes
threading Prevent UI freezing
random Story variation
2️⃣ Helper Functions
📁 Loading Files Correctly (PyInstaller‑Safe)

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 assets work even after packaging the app.

📊 Status Bar Helper
def set_status(msg):
status_var.set(msg)
root.update_idletasks()

Used to show feedback like “Generating story…”.

3️⃣ Creating the Main Window

root = tk.Tk()
root.title("Personalized AI‑Assisted Story Generator")
root.geometry("850x720")
root.minsize(850, 720)
sv_ttk.set_theme("light")
Enter fullscreen mode Exit fullscreen mode

🪟 This creates the main application window.

4️⃣ Global State Variables

Tkinter uses special variables that automatically sync with widgets.

dark_mode_var = tk.BooleanVar(value=False)
ai_mode_var = tk.BooleanVar(value=True)
Enter fullscreen mode Exit fullscreen mode
story_title_var = tk.StringVar()
story_prompt_var = tk.StringVar()
story_characters_var = tk.StringVar()
story_settings_var = tk.StringVar()
story_plot_var = tk.StringVar()
story_result_var = tk.StringVar(value="")
Enter fullscreen mode Exit fullscreen mode
story_history = []
Enter fullscreen mode Exit fullscreen mode

🧠 These act as the app’s memory.

5️⃣ Light / Dark Theme Toggle

def toggle_theme():
    bg = "#2E2E2E" if dark_mode_var.get() else "#FFFFFF"
    fg = "white" if dark_mode_var.get() else "black"
Enter fullscreen mode Exit fullscreen mode
    root.configure(bg=bg)
    for w in ["TFrame", "TLabel", "TLabelframe", "TLabelframe.Label", "TCheckbutton"]:
        style.configure(w, background=bg, foreground=fg)
Enter fullscreen mode Exit fullscreen mode

🎨 Switches colors dynamically without restarting the app.

6️⃣ Story Data (AI‑Style Building Blocks)

Instead of calling a real AI API, we simulate creativity using lists.

DEFAULT_CHARACTERS = ["a brave knight", "a curious child", "an old wizard"]
DEFAULT_SETTINGS = ["in a distant kingdom", "inside a magical forest"]
DEFAULT_PLOTS = ["faces a great challenge", "discovers a hidden secret"]
RESOLUTIONS = ["overcomes the obstacle", "learns an important lesson"]
Enter fullscreen mode Exit fullscreen mode

✨ Random combinations = infinite stories.

7️⃣ Parsing User Input Safely

def parse_user_input(input_str, default_list):
    items = [i.strip() for i in input_str.split(",") if i.strip()]
    return items if items else default_list
Enter fullscreen mode Exit fullscreen mode

✔️ Uses defaults if the user leaves fields empty.

8️⃣ Generating a Single Paragraph

def generate_ai_paragraph(title, prompt, characters, settings, plots):
    char = random.choice(characters)
    setting = random.choice(settings)
    plot = random.choice(plots)
Enter fullscreen mode Exit fullscreen mode
return f"{title} begins with {char} {setting}. One day, {char} {plot} related to {prompt}."
Enter fullscreen mode Exit fullscreen mode

🧱 Each paragraph is generated independently.

9️⃣ Building the Full Story

def generate_ai_story(title, prompt, characters_input, settings_input, plot_input, paragraphs=4):
    characters = parse_user_input(characters_input, DEFAULT_CHARACTERS)
    settings = parse_user_input(settings_input, DEFAULT_SETTINGS)
    plots = parse_user_input(plot_input, DEFAULT_PLOTS)
Enter fullscreen mode Exit fullscreen mode
    story = []
    for _ in range(paragraphs):
        story.append(generate_ai_paragraph(title, prompt, characters, settings, plots))
Enter fullscreen mode Exit fullscreen mode
    return "\n\n".join(story)
Enter fullscreen mode Exit fullscreen mode

📖 Combines paragraphs into a readable story.

🔟 Preventing UI Freezing (Threading)

def create_story():
    threading.Thread(target=_generate_story_thread, daemon=True).start()
Enter fullscreen mode Exit fullscreen mode

💡 Long tasks must run outside the UI thread.

1️⃣1️⃣ Story History Vault

def add_to_history(title, story):
    story_history.append((title, story))
    history_list.insert(tk.END, title)
Enter fullscreen mode Exit fullscreen mode

🗄 Stores and previews generated stories.

1️⃣2️⃣ Typing Animation Viewer
text_widget.after(5, type_char)

⌨️ Simulates a live typing effect—great UX for stories.

1️⃣3️⃣ Export Stories to TXT

with open(file_path, "w", encoding="utf-8") as f:
    f.write(story)
Enter fullscreen mode Exit fullscreen mode

📤 Lets users save their work locally.

1️⃣4️⃣ Building the UI Layout

ttk.Label(main, text="Story Title").grid(...)
ttk.Entry(main, textvariable=story_title_var)
Enter fullscreen mode Exit fullscreen mode

📐 Tkinter uses a grid system—rows and columns.

1️⃣5️⃣ Run the App

root.mainloop()
Enter fullscreen mode Exit fullscreen mode

🚀 Starts the event loop and launches the app.

🎉 Final Thoughts

You’ve just built:

A full desktop GUI app

A pseudo‑AI content generator

A reusable Tkinter project template

💡 Next Up?

Replace rules with a real LLM API

Save stories as JSON

Add word count & reading time

Package with PyInstaller

Top comments (0)