1. What is Tkinter?
Tkinter is Python’s built-in library for making desktop GUI applications. GUI means Graphical User Interface. A GUI program has visible elements such as:
- windows
- buttons
- labels
- text boxes
- menus
- dialog boxes
- tabs
Without Tkinter, many beginner Python programs run only in the terminal. With Tkinter, the user can click buttons, type in text boxes, and interact with a window.
2. Why Tkinter is good for beginners
Simple to start
In most Python installations, Tkinter is already available. That means you can begin building windows immediately.
Teaches core GUI ideas
You learn windows, widgets, layout, events, and callbacks. These are fundamental ideas used in many GUI frameworks.
Good for tools
Tkinter is perfect for calculators, data entry forms, small dashboards, file tools, and desktop demos.
Works well with Python code
You can connect Tkinter to your existing functions, classes, and business logic.
3. Your first Tkinter program
This is the smallest useful Tkinter program:
import tkinter as tk
root = tk.Tk()
root.title("My First Tkinter App")
root.geometry("400x200")
label = tk.Label(root, text="Hello, Tkinter!")
label.pack()
root.mainloop()
Line-by-line explanation
| Code | Meaning |
|---|---|
import tkinter as tk |
Imports the Tkinter library and gives it the short name tk. |
root = tk.Tk() |
Creates the main application window. |
root.title(...) |
Sets the text shown in the window title bar. |
root.geometry("400x200") |
Sets the width and height of the window. |
tk.Label(...) |
Creates a label widget that shows text. |
pack() |
Places the label inside the window. |
root.mainloop() |
Starts the app and keeps the window open until the user closes it. |
mainloop(), the window appears and closes immediately.
4. Important widgets in Tkinter
A widget is a visible GUI element. Here are the most common ones:
| Widget | Purpose |
|---|---|
Label |
Shows text |
Button |
Runs a function when clicked |
Entry |
Single-line text input |
Text |
Multi-line text area |
Frame |
Container for grouping widgets |
LabelFrame |
Frame with a visible title |
Notebook |
Tabbed interface |
ScrolledText |
Text area with scrollbar |
6. Getting user input with Entry
The Entry widget takes single-line text input.
import tkinter as tk
def show_name():
name = entry.get()
print("Name:", name)
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text="Show", command=show_name)
button.pack()
root.mainloop()
Important method
entry.get() reads whatever the user typed in the box.
7. Multi-line output with Text and ScrolledText
For larger output such as reports, logs, transaction history, and file paths, use a text area.
import tkinter as tk
root = tk.Tk()
text_box = tk.Text(root, height=10, width=40)
text_box.pack()
text_box.insert("end", "Hello from Tkinter!\n")
text_box.insert("end", "This is a text area.")
root.mainloop()
Useful methods
insert("end", text)adds textdelete("1.0", "end")clears all textget("1.0", "end")reads all text
For larger apps, ScrolledText is even better because it adds scrolling automatically.
8. Layout managers: pack, grid, and place
Tkinter has three main ways to position widgets:
pack()
Simple and quick. Good for basic vertical or horizontal layouts.
grid()
Best for forms. Widgets are arranged in rows and columns.
import tkinter as tk
root = tk.Tk()
tk.Label(root, text="Name").grid(row=0, column=0)
tk.Entry(root).grid(row=0, column=1)
tk.Label(root, text="Age").grid(row=1, column=0)
tk.Entry(root).grid(row=1, column=1)
root.mainloop()
place()
Places widgets at exact x-y coordinates. Usually less flexible for responsive layouts.
9. Frames and grouping widgets
A Frame is a container. It helps organize large windows into sections.
import tkinter as tk
root = tk.Tk()
top_frame = tk.Frame(root)
top_frame.pack()
bottom_frame = tk.Frame(root)
bottom_frame.pack()
tk.Label(top_frame, text="Top section").pack()
tk.Button(bottom_frame, text="Bottom button").pack()
root.mainloop()
In larger apps, frames make it easier to separate different areas such as:
- input form
- buttons section
- report section
- charts section
10. Message boxes
Message boxes show popup messages to the user.
import tkinter as tk
from tkinter import messagebox
def show_popup():
messagebox.showinfo("Info", "This is a popup")
root = tk.Tk()
tk.Button(root, text="Show Popup", command=show_popup).pack()
root.mainloop()
Common popup types
messagebox.showinfo()messagebox.showwarning()messagebox.showerror()
In real apps, they are useful for showing success messages, input mistakes, and error details.
11. Event-driven programming
Tkinter programs are event-driven. That means the program waits for events such as:
- button click
- mouse action
- key press
- window close
When the event happens, Tkinter calls the related function. This is different from simple terminal programs that run top to bottom and end.
12. Using Tkinter with your stock-analysis functions
You already built logic in function.py for:
analyze_share(...)analyze_two_shares(...)DemoTradingApp
Tkinter becomes the front-end for those functions.
What the GUI will do
- user enters share ticker and time period into input boxes
- user clicks a button
- your Python function runs
- output paths and reports are shown in a text area
- popups show success or error messages
Why this is powerful
Your business logic stays in one file, and your interface stays in another. This is a clean and professional way to design software.
13. Complete Tkinter GUI code
The following file can be saved as tkinter_app.py. It uses the functions
from your existing function.py.
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
from function import analyze_share, analyze_two_shares, DemoTradingApp
class StockAppGUI:
def __init__(self, root):
self.root = root
self.root.title("Demo Share Analysis and Trading App")
self.root.geometry("1100x750")
self.trading_app = DemoTradingApp()
self.create_widgets()
def create_widgets(self):
title = tk.Label(
self.root,
text="Demo Share Analysis and Trading App",
font=("Arial", 18, "bold")
)
title.pack(pady=10)
notebook = ttk.Notebook(self.root)
notebook.pack(fill="both", expand=True, padx=10, pady=10)
self.analysis_tab = tk.Frame(notebook)
self.compare_tab = tk.Frame(notebook)
self.trading_tab = tk.Frame(notebook)
self.output_tab = tk.Frame(notebook)
notebook.add(self.analysis_tab, text="Analyze One Share")
notebook.add(self.compare_tab, text="Compare Two Shares")
notebook.add(self.trading_tab, text="Demo Trading")
notebook.add(self.output_tab, text="Output")
self.build_analysis_tab()
self.build_compare_tab()
self.build_trading_tab()
self.build_output_tab()
def build_analysis_tab(self):
frame = self.analysis_tab
tk.Label(frame, text="Share Ticker").grid(row=0, column=0, padx=10, pady=10, sticky="w")
self.share_entry = tk.Entry(frame, width=30)
self.share_entry.insert(0, "RELIANCE.NS")
self.share_entry.grid(row=0, column=1, padx=10, pady=10)
tk.Label(frame, text="Period").grid(row=1, column=0, padx=10, pady=10, sticky="w")
self.period_entry = tk.Entry(frame, width=30)
self.period_entry.insert(0, "1mo")
self.period_entry.grid(row=1, column=1, padx=10, pady=10)
tk.Label(frame, text="Interval").grid(row=2, column=0, padx=10, pady=10, sticky="w")
self.interval_entry = tk.Entry(frame, width=30)
self.interval_entry.insert(0, "1d")
self.interval_entry.grid(row=2, column=1, padx=10, pady=10)
tk.Label(frame, text="Output Folder").grid(row=3, column=0, padx=10, pady=10, sticky="w")
self.output_dir_entry = tk.Entry(frame, width=30)
self.output_dir_entry.insert(0, "stock_output")
self.output_dir_entry.grid(row=3, column=1, padx=10, pady=10)
tk.Button(
frame,
text="Analyze Share",
command=self.run_analyze_share,
width=20
).grid(row=4, column=0, columnspan=2, pady=20)
def build_compare_tab(self):
frame = self.compare_tab
tk.Label(frame, text="First Share").grid(row=0, column=0, padx=10, pady=10, sticky="w")
self.share1_entry = tk.Entry(frame, width=30)
self.share1_entry.insert(0, "RELIANCE.NS")
self.share1_entry.grid(row=0, column=1, padx=10, pady=10)
tk.Label(frame, text="Second Share").grid(row=1, column=0, padx=10, pady=10, sticky="w")
self.share2_entry = tk.Entry(frame, width=30)
self.share2_entry.insert(0, "TCS.NS")
self.share2_entry.grid(row=1, column=1, padx=10, pady=10)
tk.Label(frame, text="Period").grid(row=2, column=0, padx=10, pady=10, sticky="w")
self.compare_period_entry = tk.Entry(frame, width=30)
self.compare_period_entry.insert(0, "1mo")
self.compare_period_entry.grid(row=2, column=1, padx=10, pady=10)
tk.Label(frame, text="Interval").grid(row=3, column=0, padx=10, pady=10, sticky="w")
self.compare_interval_entry = tk.Entry(frame, width=30)
self.compare_interval_entry.insert(0, "1d")
self.compare_interval_entry.grid(row=3, column=1, padx=10, pady=10)
tk.Label(frame, text="Output Folder").grid(row=4, column=0, padx=10, pady=10, sticky="w")
self.compare_output_dir_entry = tk.Entry(frame, width=30)
self.compare_output_dir_entry.insert(0, "stock_compare_output")
self.compare_output_dir_entry.grid(row=4, column=1, padx=10, pady=10)
tk.Button(
frame,
text="Compare Shares",
command=self.run_compare_shares,
width=20
).grid(row=5, column=0, columnspan=2, pady=20)
def build_trading_tab(self):
frame = self.trading_tab
left = tk.LabelFrame(frame, text="User Management", padx=10, pady=10)
left.grid(row=0, column=0, padx=10, pady=10, sticky="n")
tk.Label(left, text="Username").grid(row=0, column=0, padx=5, pady=5, sticky="w")
self.username_entry = tk.Entry(left, width=25)
self.username_entry.grid(row=0, column=1, padx=5, pady=5)
tk.Label(left, text="Starting Cash / Deposit").grid(row=1, column=0, padx=5, pady=5, sticky="w")
self.cash_entry = tk.Entry(left, width=25)
self.cash_entry.insert(0, "100000")
self.cash_entry.grid(row=1, column=1, padx=5, pady=5)
tk.Button(left, text="Create User", command=self.create_user, width=18).grid(row=2, column=0, pady=10)
tk.Button(left, text="Deposit Cash", command=self.deposit_cash, width=18).grid(row=2, column=1, pady=10)
middle = tk.LabelFrame(frame, text="Trading", padx=10, pady=10)
middle.grid(row=0, column=1, padx=10, pady=10, sticky="n")
tk.Label(middle, text="Ticker").grid(row=0, column=0, padx=5, pady=5, sticky="w")
self.trade_ticker_entry = tk.Entry(middle, width=25)
self.trade_ticker_entry.insert(0, "RELIANCE.NS")
self.trade_ticker_entry.grid(row=0, column=1, padx=5, pady=5)
tk.Label(middle, text="Quantity").grid(row=1, column=0, padx=5, pady=5, sticky="w")
self.quantity_entry = tk.Entry(middle, width=25)
self.quantity_entry.insert(0, "1")
self.quantity_entry.grid(row=1, column=1, padx=5, pady=5)
tk.Button(middle, text="Buy Share", command=self.buy_share, width=18).grid(row=2, column=0, pady=10)
tk.Button(middle, text="Sell Share", command=self.sell_share, width=18).grid(row=2, column=1, pady=10)
right = tk.LabelFrame(frame, text="Reports", padx=10, pady=10)
right.grid(row=0, column=2, padx=10, pady=10, sticky="n")
tk.Button(right, text="Portfolio Report", command=self.portfolio_report, width=18).grid(row=0, column=0, pady=10)
tk.Button(right, text="Transactions", command=self.show_transactions, width=18).grid(row=1, column=0, pady=10)
tk.Button(right, text="Market Snapshot", command=self.market_snapshot, width=18).grid(row=2, column=0, pady=10)
def build_output_tab(self):
self.output_text = scrolledtext.ScrolledText(self.output_tab, wrap=tk.WORD, font=("Courier New", 10))
self.output_text.pack(fill="both", expand=True, padx=10, pady=10)
def write_output(self, text):
self.output_text.insert(tk.END, text + "\n")
self.output_text.see(tk.END)
def clear_output(self):
self.output_text.delete("1.0", tk.END)
def run_analyze_share(self):
try:
self.clear_output()
share = self.share_entry.get().strip()
period = self.period_entry.get().strip()
interval = self.interval_entry.get().strip()
output_dir = self.output_dir_entry.get().strip()
result = analyze_share(
share_name=share,
period=period,
interval=interval,
output_dir=output_dir
)
self.write_output(f"Analysis completed for {share}")
self.write_output(f"Raw CSV: {result['raw_csv']}")
self.write_output(f"Raw JSON: {result['raw_json']}")
self.write_output(f"Statistics CSV: {result['stats_csv']}")
self.write_output(f"Statistics JSON: {result['stats_json']}")
self.write_output("Charts:")
for file_path in result["chart_files"]:
self.write_output(file_path)
messagebox.showinfo("Success", f"Analysis completed for {share}")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def run_compare_shares(self):
try:
self.clear_output()
share1 = self.share1_entry.get().strip()
share2 = self.share2_entry.get().strip()
period = self.compare_period_entry.get().strip()
interval = self.compare_interval_entry.get().strip()
output_dir = self.compare_output_dir_entry.get().strip()
result = analyze_two_shares(
share1=share1,
share2=share2,
period=period,
interval=interval,
output_dir=output_dir
)
self.write_output(f"Comparison completed: {share1} vs {share2}")
self.write_output(f"Statistics CSV: {result['statistics_csv']}")
self.write_output(f"Statistics JSON: {result['statistics_json']}")
self.write_output(f"Comparison CSV: {result['comparison_csv']}")
self.write_output(f"Comparison JSON: {result['comparison_json']}")
self.write_output("Charts:")
for file_path in result["chart_files"]:
self.write_output(file_path)
messagebox.showinfo("Success", f"Comparison completed: {share1} vs {share2}")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def create_user(self):
try:
username = self.username_entry.get().strip()
cash = float(self.cash_entry.get().strip())
self.trading_app.create_user(username, cash)
self.write_output(f"User created: {username} with cash {cash}")
messagebox.showinfo("Success", f"User {username} created")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def deposit_cash(self):
try:
username = self.username_entry.get().strip()
amount = float(self.cash_entry.get().strip())
self.trading_app.deposit_cash(username, amount)
self.write_output(f"Deposited {amount} into {username}")
messagebox.showinfo("Success", "Cash deposited")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def buy_share(self):
try:
username = self.username_entry.get().strip()
ticker = self.trade_ticker_entry.get().strip()
quantity = int(self.quantity_entry.get().strip())
self.trading_app.buy_share(username, ticker, quantity)
self.write_output(f"{username} bought {quantity} of {ticker}")
messagebox.showinfo("Success", "Buy completed")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def sell_share(self):
try:
username = self.username_entry.get().strip()
ticker = self.trade_ticker_entry.get().strip()
quantity = int(self.quantity_entry.get().strip())
self.trading_app.sell_share(username, ticker, quantity)
self.write_output(f"{username} sold {quantity} of {ticker}")
messagebox.showinfo("Success", "Sell completed")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def portfolio_report(self):
try:
username = self.username_entry.get().strip()
report = self.trading_app.get_portfolio_report(username)
self.clear_output()
self.write_output(f"Portfolio Report for {username}")
self.write_output(f"Cash: {report['cash']}")
self.write_output("Holdings:")
for item in report["holdings"]:
self.write_output(str(item))
self.write_output(f"Total Market Value: {report['total_market_value']}")
self.write_output(f"Total Portfolio Value: {report['total_portfolio_value']}")
self.write_output(f"Total PnL: {report['total_pnl']}")
messagebox.showinfo("Success", "Portfolio report generated")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def show_transactions(self):
try:
username = self.username_entry.get().strip()
transactions = self.trading_app.get_user_transactions(username)
self.clear_output()
self.write_output(f"Transactions for {username}")
for txn in transactions:
self.write_output(str(txn))
messagebox.showinfo("Success", "Transactions loaded")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
def market_snapshot(self):
try:
ticker = self.trade_ticker_entry.get().strip()
result = self.trading_app.save_market_snapshot(ticker, "1mo", "1d")
self.write_output(f"Market snapshot saved for {ticker}")
self.write_output(f"Raw JSON: {result['raw_json']}")
self.write_output(f"Statistics JSON: {result['stats_json']}")
messagebox.showinfo("Success", "Market snapshot saved")
except Exception as e:
messagebox.showerror("Error", str(e))
self.write_output(f"Error: {e}")
if __name__ == "__main__":
root = tk.Tk()
app = StockAppGUI(root)
root.mainloop()
14. Explanation of the full app
The class
The GUI is wrapped inside a class called StockAppGUI. This keeps the code organized.
It stores all widgets and methods together.
The constructor
def __init__(self, root):
self.root = root
self.root.title("Demo Share Analysis and Trading App")
self.root.geometry("1100x750")
self.trading_app = DemoTradingApp()
self.create_widgets()
This runs when the GUI object is created. It stores the root window, creates the trading app object, and builds the widgets.
Notebook tabs
The GUI uses ttk.Notebook to create tabs:
- Analyze One Share
- Compare Two Shares
- Demo Trading
- Output
Entry widgets
Every input field is an Entry widget. Example:
self.share_entry = tk.Entry(frame, width=30)
Button callbacks
Buttons call class methods. Example:
tk.Button(frame, text="Analyze Share", command=self.run_analyze_share)
Writing output
The output tab uses a scrolling text area:
self.output_text = scrolledtext.ScrolledText(...)
Then this helper method writes text into it:
def write_output(self, text):
self.output_text.insert(tk.END, text + "\n")
self.output_text.see(tk.END)
Error handling
Every action uses try/except. If an error happens, the app shows:
messagebox.showerror("Error", str(e))
This prevents the program from crashing badly for the user.
15. How to run the project
Step 1: install required packages
pip install yfinance pandas numpy matplotlib
Step 2: keep these files together
function.pytkinter_app.py
Step 3: run the GUI
python tkinter_app.py
What happens next?
- a window opens
- you can analyze one share
- you can compare two shares
- you can create a demo trading user
- you can buy and sell shares in the demo system
- you can generate reports and market snapshots
16. Final summary
In this lesson, you learned:
- what Tkinter is
- how to create a window
- how labels, buttons, entries, and text areas work
- how layout managers position widgets
- how popups and events work
- how to build a tabbed desktop interface
- how to connect Tkinter to your own Python functions
- how to build a complete GUI for stock analysis and demo share trading
Suggested next upgrades
- show charts inside the GUI
- use
ttk.Treeviewfor portfolio tables - add a file chooser for output folders
- add theme switching
- add dropdowns for common stock symbols
- add form validation before running actions