Tkinter چیست؟ آموزش ساخت رابط گرافیکی در Python

آموزش کامل Tkinter برای ساخت رابط گرافیکی با Python؛ از اولین پنجره و Widgetها تا چیدمان، رویدادها و ساخت یک ابزار واقعی (مبدل دما). مناسب افرادی که تازه با پایتون آشنا شدهاند و میخواهند برنامه گرافیکی بسازند.
Tkinter چیست؟ آموزش ساخت رابط گرافیکی در Python
مقدمه
تا اینجا با پایتون آشنا شدید و آن را روی ویندوز نصب کردید. برنامههایی که تا الان نوشتهاید احتمالاً همه در ترمینال اجرا میشوند — کاربر یک متن تایپ میکند و خروجی هم متنی است. اما بیشتر نرمافزارهایی که روزانه استفاده میکنید، پنجره، دکمه و فرم دارند؛ یعنی رابط گرافیکی کاربری یا GUI (Graphical User Interface).
Tkinter سادهترین راه برای ساخت همین نوع برنامهها با Python است. در این آموزش، هم مفاهیم Tkinter را یاد میگیرید و هم قدمبهقدم یک برنامه گرافیکی واقعی میسازید.
Tkinter چیست؟
Tkinter یک کتابخانه استاندارد Python است که امکان ساخت پنجره، دکمه، فیلد ورودی و سایر عناصر گرافیکی را فراهم میکند. نامش از ترکیب «Tk» (یک جعبهابزار گرافیکی قدیمی و پایدار) و «interface» میآید.
نکته مهم درباره Tkinter این است که رابط استاندارد Python برای کار با همین کتابخانه گرافیکی Tk است و در نصبهای معمول Python در دسترس قرار دارد؛ نیازی به نصب جداگانهاش ندارید. همین موضوع آن را برای شروع آموزش ساخت رابط گرافیکی با Python گزینهی اول بیشتر برنامهنویسهای تازهکار میکند.
تفاوت اصلی برنامه خطفرمانی با برنامه گرافیکی در نحوه ارتباط با کاربر است: در خط فرمان، کاربر با تایپ کردن دستور میدهد و منتظر خروجی متنی میماند؛ در برنامه گرافیکی، کاربر با کلیک، تایپ در فیلد، یا انتخاب گزینه با برنامه تعامل میکند و نتیجه هم بهصورت بصری (متن در یک Label، تغییر رنگ، باز شدن پنجره جدید و…) نمایش داده میشود.
مزایای Tkinter:
- در نصب معمول Python در دسترس است، نیازی به نصب جداگانه ندارد.
- یادگیریاش برای مبتدیها ساده است.
- برای ابزارهای داخلی، اسکریپتهای شخصی و پروژههای کوچک تا متوسط کاملاً کافی است.
محدودیتهای Tkinter:
- ظاهر پیشفرض آن نسبت به فریمورکهای مدرنتر سادهتر و قدیمیتر به نظر میرسد.
- برای اپلیکیشنهای بزرگ، پیچیده یا موبایل، انتخاب ایدهآلی نیست.
آیا Tkinter همراه Python نصب میشود؟
در نصب معمول Python برای ویندوز (چه با نصبکننده رسمی و چه با winget)، Tkinter در دسترس است و معمولاً نیازی به pip install جداگانه ندارید.
برای اینکه مطمئن شوید Tkinter روی سیستم شما در دسترس است، یک ترمینال باز کنید و این دستور را بزنید:
python -m tkinter
اگر یک پنجره کوچک آزمایشی باز شد، یعنی Tkinter آماده کار است. کافی است همان پنجره را ببندید و ادامه دهید.
ساخت اولین پنجره با Tkinter
قبل از هر Widget یا چیدمانی، هر برنامه Tkinter به یک «پنجره اصلی» نیاز دارد. یک فایل جدید به نام app.py بسازید و این کد را در آن بنویسید:
import tkinter as tk
window = tk.Tk()
window.title("اولین برنامه من")
window.geometry("300x200")
window.mainloop()
این کد را اجرا کنید:
python app.py
باید یک پنجره خالی به اندازه ۳۰۰ در ۲۰۰ پیکسل با عنوان «اولین برنامه من» باز شود.

حالا ببینیم هر خط چه کاری میکند:
import tkinter as tkکتابخانه Tkinter را وارد برنامه میکند. استفاده از نام مستعارtkیک قرارداد رایج است تا مجبور نباشید هر بار کلمه کاملtkinterرا بنویسید.tk.Tk()پنجره اصلی برنامه را میسازد. تقریباً هر برنامه Tkinter دقیقاً یک نمونه از این کلاس دارد.title()متنی که روی نوار بالای پنجره نمایش داده میشود را تنظیم میکند.geometry()اندازه اولیه پنجره را مشخص میکند؛ عدد اول عرض و عدد دوم ارتفاع، هر دو بر حسب پیکسل.mainloop()مهمترین خط کل برنامه است. این متد یک حلقه بینهایت اجرا میکند که منتظر رویدادهایی مثل کلیک، تایپ یا بستن پنجره میماند. بدون این خط، پنجره اصلاً باز نمیشود یا بلافاصله بسته میشود.
آشنایی با Widgetهای Tkinter
هر عنصری که داخل پنجره میبینید — متن، دکمه، فیلد ورودی — یک Widget نامیده میشود. مهمترین Widgetهایی که برای شروع لازم دارید:
Label
برای نمایش متن یا تصویر ثابت استفاده میشود؛ مثلاً یک عنوان یا توضیح.
label = tk.Label(window, text="سلام، این یک Label است")
label.pack()
Button
دکمهای که با کلیک روی آن، یک تابع اجرا میشود (در بخش بعدی به آن میپردازیم).
button = tk.Button(window, text="کلیک کن")
button.pack()
Entry
فیلد تکخطی برای دریافت ورودی متنی از کاربر؛ مثل نام، سن یا یک عدد.
entry = tk.Entry(window)
entry.pack()
Frame
یک کانتینر نامرئی برای گروهبندی چند Widget در کنار هم؛ وقتی چیدمان پیچیدهتر میشود، Frame کار را منظم نگه میدارد.
frame = tk.Frame(window)
frame.pack()
Text
برخلاف Entry که فقط یک خط میگیرد، Text برای متن چندخطی مناسب است؛ مثلاً یک ناحیه یادداشت.
text = tk.Text(window, height=5, width=30)
text.pack()
Checkbutton
یک گزینه روشن/خاموش (تیکدار)؛ برای انتخابهای بله/خیر مناسب است.
var = tk.IntVar()
checkbutton = tk.Checkbutton(window, text="موافقم", variable=var)
checkbutton.pack()
Radiobutton
برای انتخاب یکی از چند گزینه؛ برخلاف Checkbutton که چندتایی است، در یک گروه Radiobutton فقط یک گزینه همزمان انتخاب میشود.
var = tk.StringVar()
tk.Radiobutton(window, text="گزینه ۱", variable=var, value="1").pack()
tk.Radiobutton(window, text="گزینه ۲", variable=var, value="2").pack()
Listbox
فهرستی از گزینهها که کاربر میتواند یک یا چند مورد از آنها را انتخاب کند.
listbox = tk.Listbox(window)
listbox.insert(1, "مورد اول")
listbox.insert(2, "مورد دوم")
listbox.pack()
نکته مهم درباره تمام مثالهای بالا: هر Widget را که میسازید، باید با یکی از متدهای چیدمان (که در بخش بعدی توضیح میدهیم) روی پنجره «نمایش» بدهید — وگرنه ساخته میشود ولی هیچوقت دیده نمیشود.
چیدمان عناصر در Tkinter
ساختن یک Widget کافی نیست؛ باید به Tkinter بگویید کجای پنجره قرارش بدهد. سه روش برای این کار وجود دارد:
pack()
سادهترین روش. هر Widget را یکی پس از دیگری، بالای Widget قبلی یا کنارش قرار میدهد.
tk.Label(window, text="اول").pack()
tk.Label(window, text="دوم").pack()
برای پنجرههای ساده و خطی مناسب است، اما وقتی چیدمان پیچیدهتر شود (مثل فرم چند ستونی)، کنترل دقیق روی موقعیت هر عنصر سخت میشود.
grid()
Widgetها را در یک جدول نامرئی، بر اساس شماره ردیف (row) و ستون (column) قرار میدهد.
tk.Label(window, text="نام:").grid(row=0, column=0)
tk.Entry(window).grid(row=0, column=1)
برای فرمها (مثل نام و مقدار کنار هم) بهترین انتخاب است، چون کنترل دقیقی روی چیدمان ردیف و ستون میدهد.
place()
موقعیت دقیق هر Widget را با مختصات x و y مشخص میکند.
tk.Label(window, text="موقعیت ثابت").place(x=50, y=80)
انعطاف زیادی دارد، اما چون مختصات را دستی تنظیم میکنید، با تغییر اندازه پنجره ممکن است چیدمان بههم بریزد. برای بیشتر پروژهها، pack() یا grid() انتخاب بهتری هستند و place() را بیشتر برای موارد خاص نگه دارید.
یک قانون مهم: هیچوقت pack() و grid() را روی Widgetهای داخل یک والد مشترک با هم قاطی نکنید؛ Tkinter در این حالت خطا میدهد یا رفتار غیرمنتظره نشان میدهد. اگر لازم است هم از pack و هم از grid استفاده کنید، آنها را در Frameهای جدا از هم به کار ببرید.
کار با Button و رویدادها
دکمه بهتنهایی کاری انجام نمیدهد؛ باید با پارامتر command بگویید با کلیک روی آن، کدام تابع اجرا شود.
مثال: با کلیک روی دکمه، متن داخل یک Label تغییر میکند.
import tkinter as tk
def change_text():
label.config(text="دکمه کلیک شد!")
window = tk.Tk()
window.title("مثال Button")
label = tk.Label(window, text="هنوز کلیک نشده")
label.pack(pady=10)
button = tk.Button(window, text="کلیک کن", command=change_text)
button.pack(pady=10)
window.mainloop()

نکتهای که خیلی از تازهکارها اشتباه میکنند: در command=change_text نام تابع را بدون پرانتز مینویسیم. اگر بنویسید command=change_text()، تابع همان لحظه که برنامه اجرا میشود صدا زده میشود، نه با کلیک روی دکمه — چون پرانتز یعنی «همین حالا اجرا کن»، در حالی که Tkinter فقط به آدرس (reference) تابع نیاز دارد تا بعداً خودش صدایش بزند.
برای تغییر متن یک Label بعد از ساختهشدنش، از متد config() استفاده میکنیم — همانطور که در تابع بالا دیدید.
دریافت اطلاعات از کاربر با Entry
حالا یک مثال بسازیم که کاربر نامش را وارد کند و برنامه به او خوشآمد بگوید:
import tkinter as tk
def welcome():
name = entry.get()
label.config(text=f"سلام {name}، خوش آمدی!")
window = tk.Tk()
window.title("خوشآمدگویی")
tk.Label(window, text="نام خود را وارد کنید:").pack(pady=5)
entry = tk.Entry(window)
entry.pack(pady=5)
tk.Button(window, text="ارسال", command=welcome).pack(pady=5)
label = tk.Label(window, text="")
label.pack(pady=10)
window.mainloop()

نکته کلیدی این مثال، متد entry.get() است — این متد مقداری که کاربر داخل فیلد Entry تایپ کرده را بهصورت رشته (string) برمیگرداند. از همین الگو میتوانید برای گرفتن هر نوع ورودی متنی از کاربر استفاده کنید؛ برای مقادیر عددی هم کافی است خروجی get() را با int() یا float() تبدیل کنید.
سایر امکانات مهم Tkinter
قبل از ساخت پروژه اصلی، خوب است چند امکان دیگر Tkinter را هم بشناسید که در برنامههای واقعی زیاد به کارتان میآیند.
نوار منو (Menu)
بیشتر برنامههای دسکتاپ یک نوار منو در بالای پنجره دارند (مثل File، Edit). ساخت آن در Tkinter با کلاس Menu ساده است:
menubar = tk.Menu(window)
file_menu = tk.Menu(menubar, tearoff=0)
file_menu.add_command(label="خروج", command=window.quit)
menubar.add_cascade(label="فایل", menu=file_menu)
window.config(menu=menubar)
اینجا یک منوی «فایل» با یک گزینه «خروج» ساختیم که با کلیک، برنامه را میبندد. پارامتر tearoff=0 هم ظاهر پیشفرض قدیمی منوها (خطچین جداشدنی بالای منو) را غیرفعال میکند.
پیامهای Popup با messagebox
برای نمایش هشدار، خطا یا پیام تأیید به کاربر، بهجای ساختن پنجره جدید، از ماژول آماده messagebox استفاده میکنیم:
from tkinter import messagebox
messagebox.showinfo("پیام", "عملیات با موفقیت انجام شد")
messagebox.showerror("خطا", "مقدار واردشده معتبر نیست")
showinfo، showwarning و showerror هر کدام یک پنجره پاپآپ کوچک با آیکون مناسب باز میکنند و برای اطلاعرسانی سریع به کاربر بسیار کاربردیاند.
رسم و گرافیک با Canvas
اگر لازم شد شکل، خط یا نمودار ساده رسم کنید، Widget مخصوص این کار Canvas است:
canvas = tk.Canvas(window, width=200, height=100)
canvas.pack()
canvas.create_rectangle(20, 20, 120, 80, fill="lightblue")
canvas.create_oval(60, 40, 160, 90, outline="red")
Canvas یک ناحیه رسم آزاد در اختیارتان میگذارد که میتوانید روی آن مستطیل، بیضی، خط یا حتی تصویر بکشید — برای نمودار، بازیهای ساده یا هر جایی که نیاز به گرافیک سفارشی دارید مناسب است.
Widgetهای استایلدار با ماژول ttk
ماژول ttk نسخه استایلدارتری از Widgetهای رایج ارائه میدهد و چند Widget اضافه هم دارد که در Tkinter پایه وجود ندارند؛ مثل Combobox (لیست کشویی)، Progressbar (نوار پیشرفت) و Scale (اسلایدر عددی):
from tkinter import ttk
combo = ttk.Combobox(window, values=["گزینه ۱", "گزینه ۲", "گزینه ۳"])
combo.pack(pady=5)
progress = ttk.Progressbar(window, length=200, mode="determinate", value=40)
progress.pack(pady=5)
استفاده از این Widgetها دقیقاً شبیه Widgetهای پایه است؛ فقط بهجای tk. از ttk. استفاده میکنید و ظاهر مدرنتری میگیرید.
ساخت یک رابط گرافیکی واقعی
حالا وقتش رسیده یک پروژه کامل بسازیم: مبدل دما (سلسیوس به فارنهایت). این پروژه شامل عنوان، یک فیلد ورودی، دکمه محاسبه، و نمایش نتیجه است — دقیقاً چیزی شبیه ابزارهای کوچکی که در دنیای واقعی هم میسازید.
import tkinter as tk
from tkinter import messagebox
def convert_temperature():
try:
celsius = float(entry_celsius.get())
fahrenheit = (celsius * 9/5) + 32
label_result.config(text=f"{celsius}° سلسیوس = {fahrenheit:.1f}° فارنهایت")
except ValueError:
messagebox.showerror("خطا", "لطفاً یک عدد معتبر وارد کنید")
window = tk.Tk()
window.title("مبدل دما")
window.geometry("320x220")
frame = tk.Frame(window, padx=20, pady=20)
frame.pack()
tk.Label(frame, text="مبدل سلسیوس به فارنهایت", font=("Tahoma", 12, "bold")).grid(
row=0, column=0, columnspan=2, pady=(0, 15)
)
tk.Label(frame, text="دما (سلسیوس):").grid(row=1, column=0, sticky="e", pady=5)
entry_celsius = tk.Entry(frame, width=15)
entry_celsius.grid(row=1, column=1, pady=5)
tk.Button(frame, text="محاسبه کن", command=convert_temperature).grid(
row=2, column=0, columnspan=2, pady=10
)
label_result = tk.Label(frame, text="", font=("Tahoma", 10))
label_result.grid(row=3, column=0, columnspan=2)
window.mainloop()

بخشهای مهم این کد را با هم مرور کنیم:
- یک
Frameباpadxوpadyساختیم تا کل محتوا از لبههای پنجره فاصله داشته باشد و ظاهر شلوغی نداشته باشد. - از
grid()استفاده کردیم چون چیدمان ما شبیه یک فرم دو ستونی (برچسب و مقدار) است — دقیقاً همان موردی که در بخش چیدمان گفتیمgridبرایش مناسبتر است. - تابع
convert_temperature()مقدار Entry را میخواند، آن را به عدد اعشاری تبدیل میکند و فرمول تبدیل را اجرا میکند. - استفاده از
try/exceptحیاتی است: اگر کاربر بهجای عدد، یک متن دلخواه تایپ کند،float()خطا میدهد؛ بهجای کرش کردن برنامه، همانmessageboxکه در بخش قبل معرفی کردیم را برای نمایش خطا به کاربر صدا میزنیم. {fahrenheit:.1f}عدد را با یک رقم اعشار فرمت میکند تا خروجی تمیزتر باشد.
اگر این کد را اجرا کنید، یک ابزار واقعی و کاربردی خواهید داشت که میتوانید همین الان استفادهاش کنید یا به دلخواه گسترشش دهید (مثلاً اضافه کردن تبدیل به کلوین).
مدیریت خطاهای رایج
چند خطای رایجی که تقریباً هر مبتدیای در Tkinter تجربه میکند:
فراموش کردن mainloop()
اگر این خط را ننویسید، پنجره اصلاً باز نمیشود یا بلافاصله بعد از باز شدن بسته میشود، چون برنامه منتظر رویدادها نمیماند.
اشتباه در نام Widgetها
اگر یک Widget را با نامی متفاوت از چیزی که بعداً در کد استفاده میکنید بسازید (مثلاً متغیر را btn بگذارید ولی جای دیگر button بنویسید)، پایتون خطای NameError میدهد. نامگذاری ثابت و منظم برای متغیرهای Widget را از همان ابتدا رعایت کنید.
قاطی کردن grid و pack
همانطور که گفتیم، این دو روش چیدمان در یک والد مشترک با هم سازگار نیستند و باعث خطا میشوند. اگر خطایی شبیه «cannot use geometry manager grid inside … which already has slaves managed by pack» دیدید، دقیقاً همین مشکل است.
اشتباه در command
نوشتن command=تابع() بهجای command=تابع باعث میشود تابع بلافاصله موقع اجرای برنامه صدا زده شود، نه با کلیک — چون همانطور که در بخش Button گفتیم، پرانتز یعنی فراخوانی فوری، نه ارسال reference.
مشکل indentation
Tkinter مثل هر کد Python دیگری به تورفتگی (indentation) حساس است. اگر یک خط داخل تابع یک فاصله کمتر یا بیشتر از بقیه باشد، پایتون خطای IndentationError میدهد. از ویرایشگری مثل VS Code استفاده کنید که تورفتگی را خودکار مدیریت میکند.
ساختار پیشنهادی پروژههای Tkinter
برای یک پروژه کوچک مثل مثالهای این مقاله، نوشتن همهچیز در یک فایل کاملاً منطقی است. اما وقتی پروژه بزرگتر میشود — مثلاً چند پنجره، چند بخش منطقی، یا کد زیاد — بهتر است:
- منطق برنامه (محاسبات، پردازش داده) را از کد رابط گرافیکی جدا کنید.
- اگر چند بخش مجزا دارید (مثلاً یک فایل برای فرم ورود، یک فایل برای نمایش نتیجه)، آنها را در فایلهای جداگانه نگه دارید و در فایل اصلی import کنید.
نیازی نیست از همان ابتدا سراغ الگوهای پیچیده معماری نرمافزار بروید؛ برای یادگیری و پروژههای شخصی، همین سطح از جداسازی کاملاً کافی است.
Tkinter چه زمانی انتخاب خوبی است؟
Tkinter برای یادگیری، ابزارهای داخلی، اسکریپتهای شخصی و پروژههای کوچک تا متوسط انتخاب خوبی است — دقیقاً همان چیزی که در این مقاله ساختیم.
اگر به دنبال گزینههای دیگر برای ساخت GUI با Python هستید:
- PyQt / PySide ظاهر مدرنتر و امکانات پیشرفتهتری دارند، اما یادگیریشان سختتر است و مدل لایسنس و شرایط استفاده تجاریشان با Tkinter متفاوت است.
- Kivy برای ساخت اپلیکیشنهای موبایل و رابطهای لمسی طراحی شده و مناسب پروژههایی است که قرار است روی موبایل هم اجرا شوند.
- توسعه رابط وب (با فریمورکهایی مثل Flask یا Django به همراه HTML/CSS) وقتی گزینه بهتری است که میخواهید برنامهتان از طریق مرورگر و بدون نصب در دسترس باشد.
برای شروع یادگیری ساخت رابط گرافیکی با Python، Tkinter یکی از سادهترین گزینهها برای شروع کار است؛ وقتی به محدودیتهایش رسیدید، انتقال به گزینههای دیگر با پایهای که از Tkinter دارید سادهتر خواهد بود.
جمعبندی
در این آموزش یاد گرفتید Tkinter چیست، چطور اولین پنجره را بسازید، مهمترین Widgetها و روشهای چیدمان را بشناسید، به رویدادها با command واکنش نشان دهید، و در نهایت یک ابزار واقعی — مبدل دما — بسازید. همچنین با خطاهای رایج مبتدیها و راه پیشگیری از آنها آشنا شدید.
قدم بعدی طبیعی، بهکارگیری همین مهارتها در یک پروژه کاملتر است. در مقاله بعدی، ساخت ماشین حساب گرافیکی با Python و Tkinter، همین مفاهیم را در یک پروژه بزرگتر و عملیتر پیاده میکنیم.
سوالات متداول
آیا Tkinter رایگان است؟
بله. Tkinter بخشی از کتابخانه استاندارد Python است و کاملاً رایگان و متنباز است.
آیا برای استفاده از Tkinter باید آن را جداگانه نصب کنم؟
خیر، در نصب معمول Python روی ویندوز، Tkinter در دسترس است و معمولاً نیازی به نصب جداگانه ندارد.
تفاوت Tkinter با PyQt چیست؟
Tkinter سادهتر و مناسب شروع کار است، در حالی که PyQt ظاهر مدرنتر و امکانات بیشتری دارد اما یادگیریاش زمان بیشتری میبرد.
آیا Tkinter برای ساخت برنامههای حرفهای هم مناسب است؟
برای ابزارهای داخلی و پروژههای کوچک تا متوسط بله؛ برای اپلیکیشنهای بزرگ و پیچیده، معمولاً گزینههای دیگری مثل PyQt مناسبترند.
چرا پنجره برنامه من بلافاصله بسته میشود؟
به احتمال زیاد خط mainloop() را در انتهای کد جا انداختهاید. بدون این خط، برنامه منتظر رویدادها نمیماند و بلافاصله اجرا تمام میشود.
چه زمانی از grid و چه زمانی از pack استفاده کنم؟
برای چیدمان ساده و خطی (مثلاً چند عنصر زیر هم)، pack() کافی است. برای فرمها یا چیدمان ردیف و ستونی دقیقتر، grid() گزینه بهتری است.
آیا میتوانم ظاهر Tkinter را شخصیسازی کنم؟
بله، با تنظیم پارامترهایی مثل font، bg (رنگ پسزمینه) و fg (رنگ متن) میتوانید ظاهر Widgetها را تا حدی تغییر دهید، هرچند نسبت به فریمورکهای مدرنتر امکانات محدودتری دارد.