Python Learningاز صفر تا نوشتن پروژه از حفظ
درس ۱۱ · ابزارهای پروژه

tkinter ۱: پنجره، فرم و دکمه

حدود ۶۰ دقیقه۲ تمرین۶ سؤال آزمون
بعد از این درس می‌توانی:
  • پنجره بسازی و عنوان و اندازه‌اش را تعیین کنی
  • برچسب (Label)، جعبه‌ی ورودی (Entry) و دکمه (Button) بگذاری
  • با grid ویجت‌ها را در ردیف و ستون بچینی
  • متن جعبه را بخوانی، پاک کنی، بنویسی و پیام نشان دهی
حواست باشد

tkinter داخل مرورگر اجرا نمی‌شود، چون پنجره‌ی واقعی ویندوز می‌سازد. کدهای این درس را در VS Code کپی کن و اجرا کن (دکمه‌ی «کپی» گوشه‌ی هر کد). بعد از هر اجرا، تیک کارهایی را که انجام دادی بزن.

کوچک‌ترین برنامه‌ی پنجره‌دار

window.py
import tkinter as tk
from tkinter import ttk, messagebox

root = tk.Tk()
root.title('اولین پنجره')
root.geometry('400x200')

ttk.Label(root, text='سلام tkinter').grid(row=0, column=0, padx=10, pady=10)

root.mainloop()

grid: چیدن در ردیف و ستون

هر ویجت با grid(row=…, column=…) در یک خانه از جدول نامرئی پنجره می‌نشیند. padx/pady فاصله‌ی دورش است، sticky می‌گوید به کدام طرف خانه بچسبد ('e' شرق/راست، 'w' غرب/چپ، 'nsew' همه طرف) و columnspan چند ستون را بگیرد.

حواست باشد

grid چیزی برنمی‌گرداند (None). اگر بنویسی entry = ttk.Entry(root).grid(...) متغیر entry برابر None می‌شود. اگر بعداً به ویجت نیاز داری، ساختن و grid را در دو خط بنویس.

در پروژه‌ی فروشگاه

برچسب‌ها در خط ۷۲ پروژه در یک خط ساخته و چیده می‌شوند (چون بعداً لازم نیستند)، ولی جعبه‌ها در خط ۷۳ پروژه و خط ۷۴ پروژه دو خطی هستند.

فرم با Entry و Button

greet.py
import tkinter as tk
from tkinter import ttk, messagebox

root = tk.Tk()
root.title('فرم سلام')

ttk.Label(root, text='نام').grid(row=0, column=0, padx=8, pady=5, sticky='e')
name_entry = ttk.Entry(root, width=28)
name_entry.grid(row=0, column=1, padx=8, pady=5)

def greet():
    name = name_entry.get().strip()
    if not name:
        messagebox.showerror('خطا', 'نام را بنویس')
        return
    messagebox.showinfo('سلام', f'سلام {name}!')
    name_entry.delete(0, tk.END)

ttk.Button(root, text='سلام کن', command=greet).grid(row=1, column=0, columnspan=2, pady=10)
root.mainloop()
کارکد
خواندن متن جعبهentry.get()
پاک کردن کل متنentry.delete(0, tk.END)
نوشتن از ابتداentry.insert(0, 'متن')
پیام اطلاعاتmessagebox.showinfo('عنوان', 'متن')
پیام خطاmessagebox.showerror('عنوان', 'متن')

command=greet خود تابع را می‌دهد (بدون پرانتز). اگر command=greet() بنویسی، تابع همان لحظه‌ی ساختن دکمه اجرا می‌شود!

چند جعبه با حلقه و دیکشنری

به‌جای ساختن چهار جعبه با دست، یک حلقه آن‌ها را می‌سازد و در دیکشنری fields نگه می‌دارد:

Python
fields = {}
for row, (key, label) in enumerate([('name', 'نام کالا'), ('buy', 'قیمت خرید'), ('sell', 'قیمت فروش'), ('qty', 'تعداد')]):
    ttk.Label(root, text=label).grid(row=row, column=0, padx=8, pady=5, sticky='e')
    entry = ttk.Entry(root, width=28)
    entry.grid(row=row, column=1, padx=8, pady=5)
    fields[key] = entry

# بعداً:
print(fields['name'].get())
در پروژه‌ی فروشگاه

این دقیقاً خط ۷۰ پروژه تا خط ۷۵ پروژه برنامه است.

تمرین

ردیف و ستون (بدون پنجره)

این تمرین در مرورگر اجرا می‌شود. لیست cells را بساز که برای هر کدام از ۴ برچسب، یک تاپل (row, column, label) داشته باشد؛ برچسب‌ها در ستون ۰ و ردیف‌ها ۰ تا ۳. از enumerate استفاده کن.

Ctrl + Enter
دیدن راه‌حل (اول خودت تلاش کن)
labels = ['نام کالا', 'قیمت خرید', 'قیمت فروش', 'تعداد']
cells = []
for row, label in enumerate(labels):
    cells.append((row, 0, label))

تمرین بزرگ: ماشین‌حساب قیمت

خودت در VS Code برنامه‌ای بنویس با دو جعبه (قیمت و تعداد) و یک دکمه‌ی «حساب کن» که قیمت کل را با جداکننده‌ی هزارگان در messagebox.showinfo نشان دهد. اگر ورودی عدد نبود، با try/except ValueError پیام خطا بده.

تمرین

منطق ماشین‌حساب (بدون پنجره)

قبل از ساختن پنجره، منطقش را اینجا بنویس: تابع calc(price_text, qty_text) متن پیام را برگرداند، مثلاً calc('2500', '3') → 'قیمت کل: 7,500'. اگر تبدیل نشد، ValueError خودش بالا برود (لازم نیست بگیری).

Ctrl + Enter
دیدن راه‌حل (اول خودت تلاش کن)
def calc(price_text, qty_text):
    total = float(price_text) * int(qty_text)
    return f'قیمت کل: {total:,.0f}'

آزمون این درس

برای گذراندن این درس حداقل ۸۰٪ جواب درست لازم است. هر چند بار خواستی می‌توانی دوباره امتحان بدهی.

۱. کدام خط باید آخرین خط برنامه‌ی tkinter باشد؟
۲. entry = ttk.Entry(root).grid(row=0, column=0) چه مشکلی دارد؟
۳. command=greet() چه مشکلی دارد؟
۴. پاک کردن کامل متن یک Entry؟
۵. sticky='e' یعنی
۶. messagebox.showerror برای چیست؟