آموزش برنامه نویسی رابط گرافیکی (GUI) پایتون با Tkinter

آموزش برنامه نویسی رابط گرافیکی (GUI) پایتون با Tkinter

کتابخانه‌ Tkinter، ابزار استاندارد پایتون برای ساخت رابط های گرافیکی کاربر (GUI) است و توسعه‌ رابط های گرافیکی را برای برنامه نویسان بسیار ساده می‌کند. این کتابخانه به‌صورت چندسکویی (cross-platform) طراحی شده، به‌طوری‌که برنامه های ساخته‌شده با آن در سیستم عامل های مختلف مانند ویندوز، مک او اس و لینوکس ظاهر و عملکردی مشابه دارند.

آموزش ساخت رابط گرافیکی در پایتون با Tkinter

با اینکه گاهی از ظاهر قدیمی Tkinter انتقاد می‌شود، اما هنوز هم گزینه‌ای کاربردی و سریع برای ساخت برنامه های گرافیکی ساده و قابل اجرا در چند پلتفرم محسوب می‌شود.

در پایان این آموزش، با مفاهیم زیر آشنا خواهید شد:

  • GUI یا رابط کاربری گرافیکی چیست و چگونه با استفاده از Tkinter در پایتون ساخته می‌شود.
  • Tkinter معمولاً همراه با اکثر نسخه های پایتون نصب می‌شود، بنابراین در بیشتر مواقع نیازی به نصب جداگانه ندارد.
  • با وجود ابزارهای جدیدتر، Tkinter همچنان گزینه‌ای مناسب برای ساخت برنامه های ساده و چندسکویی است.
  • برای چیدمان عناصر در رابط کاربری Tkinter می‌توان از مدیرهای چیدمان مانند .pack()، .place() و .grid() استفاده کرد.
  • برای ساخت برنامه های تعاملی در Tkinter، می‌توان رویدادهایی مثل کلیک روی دکمه را به توابع پایتونی متصل کرد.

در این آموزش، شما ابتدا با نحوه شروع کار با Tkinter آشنا می‌شوید، سپس یاد می‌گیرید چگونه ویجت ها را مدیریت کرده و برنامه های تعاملی بسازید. در انتهای هر بخش، تمرین‌هایی برای تثبیت مفاهیم ارائه شده که به شما کمک می‌کند مهارت‌های خود را در عمل محک بزنید.

در نهایت، این آموزش با ساخت دو پروژه کاربردی جمع‌بندی می‌شود:

  • مبدل دما
  • ویرایشگر متن

پس وقت آن رسیده که شروع کنیم و گام‌به‌گام ساخت یک برنامه گرافیکی با Tkinter را یاد بگیریم!

ساخت اولین رابط کاربری گرافیکی با پایتون و Tkinter

پایه‌ای‌ترین عنصر در یک رابط کاربری گرافیکی (GUI) با Tkinter، پنجره (Window) است. پنجره ها در واقع ظروف اصلی هستند که تمام عناصر دیگر رابط گرافیکی درون آن‌ها قرار می‌گیرند. این عناصر مانند کادر متن (Text Box)، برچسب (Label) و دکمه (Button)، در دنیای Tkinter به عنوان ویجت (Widget) شناخته می‌شوند. هر ویجت باید درون یک پنجره قرار داشته باشد.

در این بخش، ابتدا یک پنجره ساده ایجاد می‌کنیم که تنها شامل یک ویجت است. یک محیط شِل پایتون (Python shell) را باز کرده و قدم‌به‌قدم با ما همراه شوید!

نکته: تمام مثال‌های کد در این آموزش روی سیستم عامل های ویندوز، مک‌اواس و اوبونتو لینوکس نسخه ۲۰.۰۴ با پایتون نسخه ۳.۱۰ تست شده‌اند.

اگر پایتون را از طریق نصب‌کننده رسمی python.org برای ویندوز یا مک نصب کرده‌اید، به‌راحتی می‌توانید کدهای این آموزش را اجرا کنید و نیازی به خواندن ادامه این بخش نیست. مستقیماً وارد آموزش شوید!

نصب Tkinter در برخی سیستم عامل ها:

مک او اس (با Homebrew):
نسخه پایتون که از طریق Homebrew نصب می‌شود، معمولاً به‌صورت پیش‌فرض کتابخانه موردنیاز Tkinter یعنی Tcl/Tk را ندارد و از نسخه قدیمیِ موجود در سیستم استفاده می‌کند. این نسخه ممکن است باعث شود نتوانید ماژول Tkinter را وارد کنید. برای جلوگیری از این مشکل، بهتر است پایتون را با نصب‌کننده رسمی مک نصب کنید.

اوبونتو لینوکس ۲۰.۰۴:
برای صرفه‌جویی در فضا، نسخه پیش‌فرض پایتون که همراه اوبونتو نصب می‌شود، از Tkinter پشتیبانی نمی‌کند. اگر می‌خواهید از همین نسخه پایتون استفاده کنید، کافی است پکیج زیر را نصب نمایید:

این دستور، ماژول Tkinter را به سیستم شما اضافه می‌کند.

توزیع‌های دیگر لینوکس:
اگر در نصب نسخه سازگار پایتون روی توزیع خاصی از لینوکس مشکل دارید، می‌توانید پایتون را از کد منبع (source code) به همراه نسخه مناسب Tcl/Tk کامپایل و نصب کنید. همچنین ابزار pyenv گزینه خوبی برای مدیریت نسخه های مختلف پایتون است.

ایجاد اولین پنجره در Tkinter

بعد از اینکه شِل پایتون را باز کردید، اولین کاری که باید انجام دهید، وارد کردن ماژول Tkinter است:

برای ایجاد یک پنجره جدید، باید نمونه ای از کلاس Tk بسازید و آن را در یک متغیر ذخیره کنید:

با اجرای این کد، یک پنجره جدید روی صفحه شما ظاهر می‌شود. ظاهر این پنجره ممکن است بسته به سیستم عامل شما متفاوت باشد. این پنجره همان محیطی است که در ادامه ویجت ها را در آن قرار خواهیم داد.

یک پنجره‌ی خالی از برنامه‌ی Tkinter در سیستم‌عامل‌های ویندوز ۱۰، مک‌اواس و اوبونتو لینوکس

در ادامه این آموزش، تصاویر ارائه‌شده مربوط به سیستم‌عامل ویندوز خواهند بود.

افزودن ویجت به پنجره در Tkinter

حالا که یک پنجره ایجاد کرده‌اید، وقت آن است که یک ویجت (Widget) به آن اضافه کنید. برای اضافه کردن متن به پنجره، می‌توانید از کلاس tk.Label استفاده کنید. برای مثال، یک ویجت Label بسازید که متن “Hello, Tkinter” را نمایش دهد و آن را در متغیری به نام greeting ذخیره کنید:

در این مرحله، پنجره‌ای که قبلاً ساختید هنوز تغییری نکرده است. در واقع، شما تنها یک ویجت Label ساخته‌اید، اما هنوز آن را به پنجره اضافه نکرده‌اید. چند روش مختلف برای اضافه کردن ویجت ها به پنجره وجود دارد، اما فعلاً می‌توانید از متد ()pack. استفاده کنید:

حالا پنجره طوری تغییر می‌کند که متن “Hello, Tkinter” در آن نمایش داده می‌شود.

مثال برنامه‌ی Tkinter با عنوان «سلام دنیا» در ویندوز ۱۰

متد ()pack باعث می‌شود که Tkinter اندازه پنجره را به‌صورت خودکار طوری تنظیم کند که ویجت کاملاً درون آن جا بگیرد.

در ادامه این خط را اجرا کنید:

در ظاهر ممکن است اتفاق خاصی نیفتد، اما توجه کنید که دیگر پرامپت جدیدی در محیط شِل (shell) ظاهر نمی‌شود.

متد window.mainloop() به پایتون می‌گوید که وارد حلقه رویدادهای Tkinter شود. این حلقه وظیفه دارد که به رویدادهایی مانند کلیک روی دکمه یا فشردن کلیدها گوش دهد. همچنین، وقتی این متد اجرا شود، اجرای کدهای بعدی تا زمانی که پنجره بسته شود متوقف خواهد شد. پس از بستن پنجره، خواهید دید که پرامپت جدید در شل ظاهر می‌شود.

⚠️ هشدار: وقتی در محیط REPL (محیط تعاملی پایتون) با Tkinter کار می‌کنید، تغییرات در پنجره به‌صورت خط‌به‌خط اعمال می‌شود. اما در صورتی که برنامه Tkinter را به‌صورت یک فایل پایتون اجرا کنید، این رفتار متفاوت است!

اگر در انتهای فایل پایتون، متد window.mainloop() را ننویسید، برنامه رابط کاربری شما اصلاً اجرا نخواهد شد و هیچ چیزی نمایش داده نمی‌شود. در محیط REPL، برای اعمال تغییرات می‌توانید به‌جای mainloop() به‌صورت مرحله‌ای از window.update() استفاده کنید تا تغییرات پس از هر خط کد نمایش داده شود.

ایجاد یک پنجره با Tkinter تنها به چند خط کد ساده نیاز دارد. اما پنجره خالی چندان کاربردی نیست! در بخش بعدی، با انواع ویجت های موجود در Tkinter و نحوه سفارشی سازی آن‌ها آشنا خواهید شد تا بتوانید رابط کاربری موردنظر خود را بسازید.

کار با ویجت ها (Widgets)

ویجت ها ستون فقرات چارچوب گرافیکی Tkinter در پایتون هستند. آن‌ها عناصری هستند که کاربران از طریق آن‌ها با برنامه شما تعامل برقرار می‌کنند. در Tkinter، هر ویجت با یک کلاس مشخص تعریف می‌شود. در ادامه، برخی از ویجت‌های پرکاربرد آورده شده‌اند:

کلاس ویجت توضیحات
Label برای نمایش متن روی صفحه استفاده می‌شود.
Button دکمه‌ای که می‌تواند شامل متن باشد و هنگام کلیک، عملی را اجرا کند.
Entry یک فیلد متنی برای ورود تنها یک خط متن.
Text فیلدی برای وارد کردن متن چندخطی.
Frame ناحیه‌ای مستطیلی برای گروه‌بندی ویجت های مرتبط یا ایجاد فاصله بین آن‌ها.

در بخش‌های بعدی آموزش، با نحوه کار با هرکدام از این ویجت ها آشنا خواهید شد. با این حال، توجه داشته باشید که Tkinter ویجت های بیشتری از این فهرست دارد.

اگر وارد دنیای ویجت های با ظاهر مدرن‌تر (که با عنوان themed widgets شناخته می‌شوند) شوید، انتخاب ویجت مناسب حتی پیچیده‌تر هم می‌شود. اما در ادامه این آموزش، فقط از ویجت های کلاسیک Tkinter استفاده خواهیم کرد.

در حال حاضر، ویجت های Tkinter به‌طور کلی به دو دسته اصلی تقسیم می‌شوند:

۱. ویجت های کلاسیک (Classic Widgets)

این ویجت ها در بسته اصلی tkinter موجودند؛ برای مثال: tkinter.Label.
ویجت های کلاسیک ساده، قابل‌درک و به‌راحتی قابل سفارشی سازی هستند. با این حال، ظاهر آن‌ها در اغلب سیستم عامل های امروزی قدیمی یا ناهماهنگ به نظر می‌رسد.

۲. ویجت‌های با ظاهر مدرن یا تم‌دار (Themed Widgets)

این دسته در زیرماژول tkinter.ttk قرار دارند؛ برای مثال: tkinter.ttk.Label.
ویجت های تم‌دار (Themed) با ظاهر بومی سیستم عامل کار می‌کنند و تجربه‌ای آشناتر برای کاربران فراهم می‌کنند. به همین دلیل، اگر می‌خواهید ظاهر برنامه شما شبیه به سایر برنامه های معمول سیستم عامل باشد، بهتر است از ویجت های ttk استفاده کنید.

بسیاری از این ویجت های تم‌دار، جایگزین مستقیمی برای نسخه های کلاسیک خود هستند و تنها تفاوت آن‌ها در ظاهر مدرن‌ترشان است. همچنین، برخی ویجت های جدید مانند نوار پیشرفت (Progress Bar) تنها در مجموعه ویجت های تم‌دار وجود دارند و در نسخه های قدیمی در دسترس نیستند.

با این حال، برخی ویجت های کلاسیک که معادل تم‌دار ندارند، همچنان باید از نسخه کلاسیک آن‌ها استفاده کرد.

💡 نکته: ویجت های ttk به‌طور پیش‌فرض از ظاهر بومی سیستم‌عامل استفاده می‌کنند، اما شما می‌توانید ظاهر آن‌ها را از طریق تِم (Theme) تغییر دهید؛ برای مثال به حالت تاریک یا روشن. تم ها مجموعه‌ای از استایل های قابل‌استفاده مجدد هستند، شبیه به فایل های CSS در طراحی صفحات وب.

برای امکان تغییر استایل، بیشتر اطلاعات ظاهری ویجت های ttk به اجزای جداگانه‌ای منتقل شده‌اند. این تفکیک از نظر طراحی مزیت محسوب می‌شود، اما باعث پیچیدگی در سفارشی‌سازی آن‌ها نسبت به ویجت های کلاسیک می‌شود.

استفاده همزمان از ویجت های کلاسیک و تم‌دار

برای استفاده از هر دو نوع ویجت در یک برنامه، معمولاً به‌صورت زیر آن‌ها را فراخوانی می‌کنیم:

با این کار، می‌توانیم به‌وضوح از tk.Label یا ttk.Label استفاده کنیم:

استفاده از import با علامت *

در برخی موارد ممکن است بخواهید ویجت های کلاسیک را با نمونه های تم دار جایگزین کنید. برای این کار می‌توانید از وارد کردن سراسری (Wildcard Import) استفاده کنید:

در این حالت، اگر ویجت تم دار موجود باشد، به‌صورت خودکار از آن استفاده خواهد شد:
⚠️ هشدار: ترتیب این دو خط import بسیار مهم است. ابتدا باید tkinter و سپس ttk را وارد کنید.
با این حال، استفاده از import * معمولاً توصیه نمی‌شود، چون باعث ابهام در کد می‌شود و خوانایی آن را کاهش می‌دهد. مگر اینکه به‌طور آگاهانه و در شرایط خاص انجام شود.

برای مشاهده فهرست کامل ویجت های Tkinter، می‌توانید به بخش های «Basic Widgets» و «More Widgets» در آموزش TkDocs مراجعه کنید. با اینکه این مستندات بیشتر بر روی ویجت های تم‌دار معرفی‌شده در Tcl/Tk نسخه ۸.۵ تمرکز دارند، اما بسیاری از مطالب آن‌ها برای ویجت های کلاسیک نیز کاربردی هستند.

نمایش متن و تصویر با استفاده از ویجت Label

ویجت های Label برای نمایش متن یا تصویر در رابط گرافیکی استفاده می‌شوند. متنی که در این ویجت نمایش داده می‌شود، توسط کاربر قابل ویرایش نیست و صرفاً برای نمایش است.

همان‌طور که در ابتدای این آموزش دیدید، می‌توانید با نمونه سازی از کلاس Label و ارسال یک رشته متنی به پارامتر text، یک ویجت Label ایجاد کنید:

ویجت های Label به‌طور پیش‌فرض از رنگ متن و پس‌زمینه تعیین‌شده توسط سیستم عامل استفاده می‌کنند. معمولاً این رنگ ها به‌ترتیب مشکی و سفید هستند، اما در صورتی که تنظیمات سیستم عامل شما متفاوت باشد، ممکن است رنگ های دیگری ببینید.

تغییر رنگ متن و پس‌زمینه

می‌توانید رنگ متن و پس‌زمینه را با استفاده از پارامترهای foreground (یا مخفف fg) و background (یا مخفف bg) تنظیم کنید:

یا با استفاده از نگارش کوتاه‌تر:

رنگ های پشتیبانی شده

برخی از نام های رنگی معتبر شامل موارد زیر هستند:

  • "red" (قرمز)

  • "orange" (نارنجی)

  • "yellow" (زرد)

  • "green" (سبز)

  • "blue" (آبی)

  • "purple" (بنفش)

بسیاری از نام های رنگ HTML نیز در Tkinter قابل استفاده‌اند. برای مشاهده فهرست کامل رنگ ها، از جمله رنگ های خاص سیستم عامل های macOS و Windows، می‌توانید به راهنمای رنگ ها در Tkinter مراجعه کنید.

استفاده از رنگ های HEX

همچنین می‌توانید از کدهای رنگ هگزادسیمال (hexadecimal) برای تعریف رنگ استفاده کنید:

کد بالا پس‌زمینه برچسب را به رنگ آبی روشن تنظیم می‌کند. اگرچه استفاده از کدهای HEX ممکن است کمتر قابل خواندن باشد، اما انعطاف‌پذیری بیشتری نسبت به نام های رنگ دارد. خوشبختانه ابزارهای زیادی برای انتخاب کد رنگ HEX به‌صورت بصری وجود دارد.

تنظیم عرض و ارتفاع ویجت Label

می‌توانید اندازه ویجت Label را نیز با استفاده از پارامترهای width (عرض) و height (ارتفاع) مشخص کنید:

مقادیر width و height به تعداد کاراکترهای متنی (برای عرض) و تعداد خطوط متنی (برای ارتفاع) اشاره دارند. این اندازه ها به پیکسل نیستند، بلکه وابسته به فونت و اندازه متن هستند.

در ادامه آموزش، با سایر ویژگی های قابل تنظیم در ویجت Label و همچنین ویجت های دیگر در Tkinter آشنا خواهید شد.

در اینجا نمای برچسب (Label) ایجادشده در یک پنجره Tkinter را مشاهده می‌کنید:

یک پنجره Tkinter شامل یک دکمه با پس‌زمینه‌ی مشکی و متن سفید که عبارت «Hello, Tkinter» را نمایش می‌دهد.

ممکن است عجیب به نظر برسد که این برچسب در پنجره به‌صورت مربعی نمایش داده نمی‌شود، حتی با اینکه مقادیر width و height هر دو برابر با ۱۰ تعیین شده‌اند. دلیل این موضوع این است که اندازه گیری عرض و ارتفاع در Tkinter براساس واحدهای متنی (text units) انجام می‌شود.
هر واحد افقی متنی برابر با عرض کاراکتر “۰” (عدد صفر) در فونت پیش‌فرض سیستم است. به‌طور مشابه، هر واحد عمودی نیز بر اساس ارتفاع همین کاراکتر تعیین می‌شود.

🔔 نکته: برای اندازه گیری عرض و ارتفاع، Tkinter از واحدهای متنی استفاده می‌کند (نه پیکسل، سانتی‌متر یا اینچ) تا عملکرد رابط کاربری روی سیستم‌های مختلف ثابت و یکنواخت باقی بماند.

این روش باعث می‌شود اندازه‌ی ویجت ها نسبت به فونت پیش‌فرض سیستم کاربر تنظیم شود، تا متون به‌درستی درون برچسب‌ها و دکمه‌ها جا بگیرند، صرف‌نظر از اینکه برنامه روی چه سیستمی اجرا می‌شود.

نمایش دکمه های قابل کلیک با ویجت Button

ویجت های دکمه (Button) برای ایجاد دکمه هایی به‌کار می‌روند که کاربر بتواند روی آن‌ها کلیک کند. این دکمه ها را می‌توان به‌گونه‌ای پیکربندی کرد که هنگام کلیک، یک تابع خاص را اجرا کنند. (نحوه اتصال دکمه ها به توابع را در بخش بعدی خواهید دید.)

در حال حاضر، فقط با نحوه ساخت و استایل دهی به دکمه آشنا شوید.

ویجت های Button و Label شباهت زیادی به یکدیگر دارند. در واقع، می‌توان گفت یک دکمه چیزی جز یک برچسب قابل کلیک نیست! بسیاری از آرگومان هایی که برای ساخت و استایل دهی Label به‌کار می‌روند، برای دکمه ها هم قابل استفاده هستند.

مثلاً کد زیر، دکمه‌ای با پس‌زمینه آبی و متن زرد ایجاد می‌کند. همچنین عرض و ارتفاع آن را به‌ترتیب روی ۲۵ و ۵ واحد متنی تنظیم می‌کند:

در یک پنجره Tkinter، این دکمه به‌شکل زیر ظاهر می‌شود:
یک پنجره‌ی Tkinter شامل یک دکمه با پس‌زمینه‌ی آبی و متن زرد که عبارت «Click me!» را نمایش می‌دهد.

خیلی جالبه! حالا می‌توانید از دو ویجت بعدی برای دریافت ورودی متنی از کاربر استفاده کنید.

دریافت ورودی کاربر با استفاده از ویجت Entry در Tkinter

زمانی‌که قصد دارید متن کوتاهی از کاربر دریافت کنید، مانند نام یا آدرس ایمیل، ویجت Entry گزینه‌ای بسیار مناسب خواهد بود. این ویجت یک کادر متنی کوچک در اختیار کاربر قرار می‌دهد تا اطلاعات مورد نظر خود را وارد کند.

فرآیند ایجاد و شخصی‌سازی ویجت Entry تقریباً مشابه ویجت های Label و Button است. برای نمونه، قطعه کد زیر یک کادر متنی با پس زمینه آبی، رنگ متن زرد و عرض ۵۰ واحد متنی ایجاد می‌کند:

نکته قابل‌توجه در مورد ویجت Entry، نحوه استفاده از آن جهت دریافت اطلاعات ورودی از کاربر است. این ویجت سه عملیات اصلی را پشتیبانی می‌کند:

  • دریافت مقدار متنی واردشده با متد .get()

  • حذف محتوا با متد .delete()

  • درج متن جدید با متد .insert()

برای درک بهتر عملکرد ویجت Entry، پیشنهاد می‌شود یک نمونه از آن را در محیط تعاملی (Python Shell) اجرا و بررسی کنید. ابتدا ماژول Tkinter را وارد کرده و یک پنجره جدید ایجاد نمایید:

سپس یک برچسب (Label) به همراه یک کادر متنی Entry ایجاد کنید:
برچسب ایجادشده مشخص می‌کند چه نوع اطلاعاتی باید در ویجت Entry وارد شود. اگرچه این برچسب محدودیتی اعمال نمی‌کند، اما نقش راهنما را برای کاربر ایفا می‌نماید. اکنون با استفاده از متد .pack()، ویجت ها را به پنجره اضافه کنید تا قابل‌نمایش شوند:

در ادامه، ظاهر این پنجره را مشاهده می‌کنید:

یک پنجره Tkinter شامل یک ویجت Entry به همراه یک Label با عنوان «Name»

توجه داشته باشید که متد .pack() به صورت پیش‌فرض عناصر را به شکل عمودی در مرکز پنجره قرار می‌دهد.

اکنون می‌توانید با کلیک بر روی کادر متنی، عبارتی مانند Real Python را وارد نمایید:

یک پنجره Tkinter شامل یک ویجت Entry با متنی به نام «Real Python»

در این بخش، متنی را در ویجت Entry وارد کرده‌اید، اما این متن هنوز به برنامه شما منتقل نشده است. برای دریافت متن و اختصاص آن به یک متغیر به نام name می‌توانید از متد .get() استفاده کنید:

علاوه بر دریافت متن، می‌توانید متن موجود در Entry را حذف کنید. متد .delete() برای این کار به کار می‌رود و یک آرگومان عدد صحیح دریافت می‌کند که مشخص می‌کند کدام کاراکتر باید حذف شود. برای مثال، قطعه کد زیر نشان می‌دهد که .delete(0) اولین کاراکتر موجود در Entry را حذف می‌کند:

پس از اجرای این دستور، متن موجود در ویجت به این صورت تغییر می‌کند:

یک پنجره Tkinter حاوی یک ویجت Entry با متن "eal Python"

نکته: درست مانند رشته های (string) پایتون، ایندکس گذاری کاراکترهای موجود در Entry نیز از صفر آغاز می‌شود.

اگر بخواهید چند کاراکتر را به طور هم‌زمان حذف کنید، می‌توانید یک آرگومان دوم نیز به .delete() بدهید که نشان می‌دهد حذف تا کدام ایندکس ادامه داشته باشد. برای نمونه، کد زیر چهار حرف اول را از Entry حذف می‌کند:

حالا متن باقی‌مانده به این صورت است:

یک پنجره Tkinter حاوی یک ویجت Entry با متن "Python"

متد Entry.delete() بسیار شبیه به برش رشته ها (string slicing) در پایتون عمل می‌کند؛ آرگومان اول ایندکس شروع حذف و آرگومان دوم ایندکس پایان حذف (که خود آن کاراکتر حذف نمی‌شود) را مشخص می‌کند. همچنین، اگر بخواهید تمام متن موجود در Entry را پاک کنید، می‌توانید از ثابت tk.END به عنوان آرگومان دوم استفاده کنید:

پس از این دستور، جعبه متن کاملاً خالی خواهد شد:

یک پنجره Tkinter حاوی یک ویجت Entry با برچسب "Name"

در مقابل، می‌توانید متن جدیدی را نیز وارد Entry کنید. برای این کار متد .insert() استفاده می‌شود:

اکنون پنجره متن Python را نمایش می‌دهد:

یک پنجره Tkinter حاوی یک ویجت Entry با متن "Python"

آرگومان اول متد .insert() مشخص می‌کند که متن در چه موقعیتی درج شود. اگر Entry خالی باشد، متن وارد شده همیشه در ابتدای ویجت قرار می‌گیرد، صرف‌نظر از اینکه چه مقداری به عنوان آرگومان اول وارد کرده‌اید. برای مثال، اگر به جای ۰ عدد ۱۰۰ را وارد می‌کردید، باز هم متن از ابتدای Entry درج می‌شد.

اگر Entry قبلاً دارای متنی باشد، متد .insert() متن جدید را در موقعیت مشخص‌شده درج می‌کند و باقی متن را به سمت راست جابه‌جا می‌کند:

در نتیجه، متن ویجت به صورت Real Python درخواهد آمد:

یک پنجره Tkinter شامل یک ویجت Entry با متنی به نام «Real Python»

ویجت های Entry برای دریافت مقادیر متنی کوچک از کاربر بسیار مناسب‌اند. با این حال، چون فقط روی یک خط نمایش داده می‌شوند، برای دریافت مقادیر متنی طولانی چندان کاربردی نیستند. برای این موارد، از ویجت های Text استفاده می‌شود که در ادامه به آن‌ها خواهیم پرداخت.

دریافت ورودی چندخطی از کاربر با استفاده از ویجت های Text

ویجت های Text برای وارد کردن متن به کار می‌روند و از این نظر شبیه به ویجت های Entry هستند. تفاوت اصلی در این است که ویجت های Text می‌توانند شامل چندین خط متن باشند. بنابراین، با استفاده از Text، کاربر می‌تواند یک پاراگراف یا حتی چندین صفحه متن را وارد کند.

مشابه ویجت های Entry، سه عملیات اصلی را می‌توان روی ابزارک‌های Text انجام داد:

  • دریافت متن با .get()

  • حذف متن با .delete()

  • درج متن با .insert()

هرچند نام این متدها همانند متدهای Entry است، اما نحوه عملکرد آن‌ها کمی متفاوت است. در ادامه با ساخت یک ویجت Text و مشاهده قابلیت های آن، این تفاوت ها را بررسی می‌کنیم.

نکته:
آیا هنوز پنجره ایجادشده در بخش قبلی باز است؟
اگر بله، می‌توانید آن را با دستور زیر ببندید:

همچنین می‌توانید با کلیک روی دکمه بستن (Close) پنجره را به صورت دستی ببندید.

آموزش های کاربردی پایتون

  1. راهنمای گام به گام یادگیری برنامه نویسی پایتون در سال 2025 برای مبتدیان
  2. آموزش پروژه محور طراحی سایت با پایتون و جنگو مختص بازار کار
  3. آموزش بهینه سازی کدها در برنامه نویسی پایتون
  4. 10 کاربرد برنامه نویسی پایتون
  5. نکات مهم در یادگیری برنامه نویسی پایتون برای تازه کارها
  6. آموزش ساخت ربات گرید با پایتون برای معاملات الگوریتمی
  7. آموزش تشخیص نفوذ با یادگیری ماشین و پایتون
  8. سورس و پروژه رایگان پایتون

 

اکنون در محیط شل پایتون، یک پنجره جدید ایجاد کرده و یک ویجت Text در آن قرار دهید:

به طور پیش‌فرض، جعبه های متنی (Text) از ویجت های Entry بزرگ‌تر هستند. پنجره‌ای که در بالا ایجاد شده است، به این شکل است:

یک پنجره Tkinter حاوی ویجت جعبه متن

برای فعال کردن کادر متن، در هر جایی از پنجره کلیک کنید. کلمه Hello را تایپ کنید. سپس Enter را فشار دهید و در خط دوم World را تایپ کنید. اکنون پنجره باید به شکل زیر باشد:

یک پنجره Tkinter حاوی یک ویجت جعبه متن با متن "سلام دنیا"

دریافت متن از ابزارک Text

مشابه Entry، می‌توانید متن را با استفاده از متد .get() دریافت کنید. با این حال، اگر بدون آرگومان .get() را فراخوانی کنید، برخلاف Entry که کل متن را بازمی‌گرداند، در اینجا خطا ایجاد می‌شود:

متد Text.get() حداقل به یک آرگومان نیاز دارد. اگر تنها یک اندیس (Index) به آن بدهید، یک کاراکتر برمی‌گرداند. برای دریافت چند کاراکتر، باید اندیس شروع و اندیس پایان را مشخص کنید.

از آنجایی که ویجت Text می‌تواند چندین خط متن داشته باشد، اندیس دهی در آن کمی متفاوت است:

  • شماره خط (شروع از ۱)

  • شماره کاراکتر در آن خط (شروع از ۰)

برای مشخص کردن یک اندیس، باید رشته ای به فرمت "<line>.<char>" بسازید. به عنوان نمونه:

  • "1.0" به معنای اولین کاراکتر در خط اول است.

  • "2.3" به معنای چهارمین کاراکتر در خط دوم است.

برای دریافت اولین حرف از جعبه متنی ایجادشده، اینطور عمل کنید:

کلمه Hello پنج حرف دارد و چون شماره کاراکترها از صفر شروع می‌شود، حرف o در موقعیت ۴ قرار دارد. برای دریافت کل واژه Hello باید اندیس شروع را "1.0" و اندیس پایان را "1.5" تعیین کنید (مشابه برش رشته ها در پایتون، اندیس پایان شامل نمی‌شود):
برای دریافت واژه World که در خط دوم قرار دارد، کافی است شماره خط را تغییر دهید:
اگر بخواهید تمام متن موجود در جعبه متنی را دریافت کنید، از "1.0" به عنوان اندیس شروع و از ثابت tk.END به عنوان اندیس پایان استفاده کنید:
توجه داشته باشید که متن بازگردانده‌شده شامل نویسه های خط جدید (\n) نیز می‌شود. همچنین، در ویجت Text، هر خط با یک نویسه خط جدید خاتمه می‌یابد، حتی آخرین خط.

حذف متن در ابزارک Text

برای حذف متن از جعبه متنی، از متد .delete() استفاده می‌شود. این متد عملکردی مشابه با .delete() در ویجت Entry دارد و به دو روش قابل استفاده است:

  • با یک آرگومان

  • با دو آرگومان

در حالت تک آرگومانی، اندیس کاراکتری که می‌خواهید حذف شود را به .delete() می‌دهید. برای نمونه، دستور زیر اولین کاراکتر (یعنی حرف H) را حذف می‌کند:

پس از این عملیات، اولین خط در جعبه متنی به صورت ello نمایش داده می‌شود:

یک پنجره‌ی Tkinter حاوی یک ویجت جعبه‌ی متن با متن «ello world»

در حالت دوم که .delete() دو آرگومان می‌گیرد، شما باید دو ایندکس وارد کنید تا یک بازه از کاراکترها، از ایندکس اول تا قبل از ایندکس دوم، حذف شوند.

برای مثال، برای حذف باقی‌مانده کلمه ello از خط اول ویجت متنی، از ایندکس های “1.0” و “1.4” استفاده کنید:

میبینید که متن از خط اول حذف شده است. حالا یک خط خالی در بالا وجود دارد و کلمه‌ World در خط دوم باقی مانده است:

یک پنجره Tkinter حاوی یک ویجت جعبه متن با خط اول خالی و متن "world" در خط دوم

حتی اگر چیزی روی خط اول نمی‌بینید، باز هم یک کاراکتر در آنجا وجود دارد؛ یک کاراکتر خط جدید (newline)! می‌توانید با استفاده از .get() این موضوع را بررسی کنید:

اگر این کاراکتر را حذف کنید، باقی محتوای ویجت متنی یک خط به بالا منتقل خواهد شد:
حالا کلمه World در خط اول ویجت متنی قرار گرفته است:

یک پنجره‌ی Tkinter حاوی یک ویجت جعبه‌ی متن با متن «world»

سعی کنید باقی متن داخل ویجت را هم پاک کنید. ایندکس شروع را “1.0” قرار دهید و برای ایندکس پایان از tk.END استفاده کنید:

ویجت متنی حالا کاملاً خالی شده است:

یک پنجره Tkinter حاوی ویجت جعبه متن

شما می‌توانید با استفاده از .insert() متن جدیدی داخل ویجت متنی وارد کنید:

این دستور کلمه Hello را در ابتدای ویجت متنی وارد می‌کند، با استفاده از همان فرمت "<line>.<column>"  که برای .get() هم استفاده می‌شد:

یک پنجره‌ی Tkinter حاوی یک ویجت جعبه‌ی متن با متن «hello»

حالا ببینید اگر سعی کنید کلمه World را روی خط دوم وارد کنید چه اتفاقی می‌افتد:

به جای اینکه متن روی خط دوم درج شود، به انتهای خط اول اضافه می‌شود:

یک پنجره Tkinter حاوی یک ویجت جعبه متن با متن HelloWorld در یک خط

اگر می‌خواهید متن روی یک خط جدید درج شود، باید یک کاراکتر خط جدید (\n) به صورت دستی داخل رشته وارد شده قرار دهید:

حالا World در خط دوم ویجت متنی قرار گرفته است:

یک پنجره Tkinter حاوی یک ویجت جعبه متن با متن "سلام دنیا"

عملکرد .insert() به یکی از دو صورت زیر است:

  • اگر در موقعیت مشخص‌شده متنی وجود داشته باشد یا بعد از آن، متن جدید درج می‌شود.

  • اگر موقعیت مشخص‌شده بعد از آخرین کاراکتر باشد، متن به انتهای آن خط افزوده می‌شود.

معمولاً پیگیری موقعیت آخرین کاراکتر کار راحتی نیست. بهترین روش برای درج متن در انتهای ویجت متنی، این است که tk.END را به عنوان پارامتر اول به .insert() بدهید:

فراموش نکنید که اگر می‌خواهید متن جدید روی یک خط جدید قرار بگیرد، باید یک کاراکتر خط جدید (\n) ابتدای رشته اضافه کنید:
ویجت های Label، Button، Entry و Text تنها چند نمونه از ویجت های موجود در Tkinter هستند. ویجت های دیگری هم وجود دارند، مانند ویجت هایی برای چک باکس ها، دکمه های رادیویی، اسکرول بارها و نوارهای پیشرفت (progress bars).

اختصاص دادن ویجت ها به فریم ها با استفاده از ویجت Frame

در این بخش، شما فقط با پنج ویجت کار خواهید کرد:

  • Label

  • Button

  • Entry

  • Text

  • Frame

این چهار ویجتی هستند که قبلاً با آن‌ها آشنا شده‌اید، به اضافه ویجت Frame. ویجت Frame برای سازماندهی چیدمان ویجت ها در یک برنامه اهمیت زیادی دارد.

قبل از اینکه وارد جزئیات مربوط به چیدمان بصری ویجت ها شوید، بیایید دقیق‌تر ببینیم که ویجت Frame چگونه کار می‌کند و چطور می‌توان سایر ویجت ها را به آن نسبت داد. اسکریپت زیر یک ویجت Frame خالی ایجاد می‌کند و آن را به پنجره اصلی برنامه اختصاص می‌دهد:

دستور frame.pack() فریم را داخل پنجره قرار می‌دهد تا پنجره اندازه خود را تا حد ممکن کوچک کند و فقط فضای لازم برای فریم را در بر بگیرد. زمانی که اسکریپت بالا را اجرا می‌کنید، خروجی بسیار ساده‌ای مشاهده می‌کنید:

یک پنجره Tkinter حاوی یک ویجت Frame خالی

ویجت Frame را بهتر است به عنوان یک ظرف برای سایر ویجت ها در نظر بگیرید. شما می‌توانید با تعیین مشخصه master برای یک ویجت، آن را به یک فریم نسبت دهید:

برای اینکه بهتر درک کنید این فرآیند چگونه کار می‌کند، یک اسکریپت بنویسید که دو ویجت Frame به نام های frame_a و frame_b ایجاد کند. در این اسکریپت، frame_a شامل یک لیبل با متن “I’m in Frame A” و frame_b شامل لیبلی با متن “I’m in Frame B” خواهد بود. یکی از روش های انجام این کار به این صورت است:

دقت کنید که ابتدا frame_a به پنجره اضافه شده و سپس frame_b. بنابراین، در پنجره ای که باز می‌شود، لیبل مربوط به frame_a بالای لیبل frame_b نمایش داده می‌شود:

یک پنجره Tkinter شامل دو ویجت Frame است که به صورت عمودی روی هم قرار گرفته‌اند، به طوری که متن «I'm in Frame A» در Frame بالایی و «I'm in Frame B» در Frame پایینی قرار دارد.

حالا ببینید چه اتفاقی می‌افتد اگر ترتیب frame_a.pack() و frame_b.pack() را عوض کنید:

در این حالت، خروجی به این صورت تغییر می‌کند:

یک پنجره Tkinter شامل دو ویجت Frame است که به صورت عمودی روی هم قرار گرفته‌اند، به طوری که متن «I'm in Frame B» در Frame بالایی و «I'm in Frame A» در Frame پایینی قرار دارد.

حالا لیبل label_b در بالا قرار گرفته است. چون label_b به frame_b نسبت داده شده، به هرجایی که frame_b قرار بگیرد، منتقل می‌شود.

تمام ویجت هایی که تا اینجا یاد گرفته‌اید — یعنی Label، Button، Entry و Text — هنگام ساخته شدن دارای یک ویژگی master هستند که می‌توانید با تعیین آن مشخص کنید که هر ویجت به کدام فریم تعلق داشته باشد.

استفاده از ویجت های Frame راهی عالی برای سازماندهی منطقی سایر ویجت هاست. ویجت های مرتبط می‌توانند به یک فریم نسبت داده شوند، به طوری که اگر آن فریم در پنجره جابه‌جا شود، ویجت‌های مربوطه نیز همراه آن حرکت کنند.

نکته: اگر هنگام ساخت یک ویجت، آرگومان master را مشخص نکنید، ویجت به طور پیش‌فرض داخل پنجره سطح بالای (Top-Level Window) قرار می‌گیرد.

علاوه بر گروه‌بندی منطقی ویجت ها، ویجت Frame می‌تواند به ظاهر گرافیکی برنامه شما نیز جلوه بیشتری بدهد. در ادامه خواهید دید که چطور می‌توانید انواع مختلفی از حاشیه ها (border) را برای ویجت های Frame ایجاد کنید.

تنظیم ظاهر Frame با استفاده از ویژگی relief

ویجت های Frame را می‌توان با ویژگی relief پیکربندی کرد تا یک حاشیه دور آن‌ها ایجاد شود. می‌توانید مقدار relief را روی یکی از مقادیر زیر تنظیم کنید:

  • tk.FLAT: بدون اثر حاشیه (مقدار پیش‌فرض)

  • tk.SUNKEN: ایجاد یک ظاهر فرو رفته

  • tk.RAISED: ایجاد یک ظاهر برجسته

  • tk.GROOVE: ایجاد یک حاشیه شیاردار

  • tk.RIDGE: ایجاد یک حاشیه لب‌دار

برای اعمال این جلوه حاشیه، باید ویژگی borderwidth را روی مقداری بیشتر از 1 تنظیم کنید. این ویژگی عرض حاشیه را بر حسب پیکسل تعیین می‌کند. بهترین روش برای درک بهتر از شکل ظاهری هر یک از این جلوه ها، دیدن آن‌ها در عمل است. اسکریپت زیر پنج ویجت Frame را در یک پنجره قرار می‌دهد، که هرکدام دارای مقدار متفاوتی برای relief هستند:

شرح این اسکریپت:

  • خطوط 3 تا 9 یک دیکشنری ایجاد می‌کنند که کلیدهای آن نام جلوه‌های مختلف relief در Tkinter هستند و مقادیر آن‌ها اشیای مربوط به Tkinter هستند. این دیکشنری در متغیر border_effects ذخیره می‌شود.

  • خط 13 یک حلقه for را برای پیمایش در آیتم‌های دیکشنری border_effects آغاز می‌کند.

  • خط 14 یک ویجت Frame جدید ایجاد کرده و آن را به شیء window نسبت می‌دهد. ویژگی relief به مقدار مناسب از دیکشنری تنظیم می‌شود و borderwidth روی 5 قرار می‌گیرد تا جلوه‌ی حاشیه قابل مشاهده باشد.

  • خط 15 ویجت Frame را با استفاده از متد .pack() در پنجره قرار می‌دهد. آرگومان side به Tkinter می‌گوید که Frameها را در کدام جهت قرار دهد. (در بخش بعدی بیشتر درباره این موضوع خواهید خواند.)

  • خطوط 16 و 17 یک ویجت Label برای نمایش نام جلوه relief ایجاد کرده و آن را داخل Frame قرار می‌دهد.

خروجی پنجره حاصل از اجرای این اسکریپت:

یک پنجره Tkinter شامل ۵ ویجت Frame که هر کدام یکی از پنج مقدار برجستگی (relief values) tk.FLAT، tk.SUNKET، tk.RAISED، tk.GROOVE و tk.RIDGE را دارند.

در این تصویر، می‌توانید جلوه‌های زیر را مشاهده کنید:

  • tk.FLAT: Frame را به صورت کاملاً تخت نمایش می‌دهد.

  • tk.SUNKEN: حاشیه‌ای اضافه می‌کند که باعث می‌شود Frame به نظر برسد داخل پنجره فرو رفته است.

  • tk.RAISED: حاشیه‌ای ایجاد می‌کند که باعث می‌شود Frame از صفحه بیرون زده به نظر برسد.

  • tk.GROOVE: حاشیه‌ای به شکل یک شیار دور Frame ایجاد می‌کند.

  • tk.RIDGE: نمایی شبیه لبه برجسته در اطراف Frame ایجاد می‌کند.

این جلوه‌ها می‌توانند به برنامه گرافیکی شما در Tkinter جلوه‌ای بصری و جذاب‌تر ببخشند.

درک نام گذاری ویجت ها

هنگامی که یک ویجت ایجاد می‌کنید، می‌توانید هر نام معتبری که در پایتون مجاز است به آن اختصاص دهید. معمولاً توصیه می‌شود که در نام متغیر اختصاص داده شده به ویجت، به نام کلاس ویجت نیز اشاره شود. برای مثال، اگر یک ویجت Label برای نمایش نام کاربر دارید، ممکن است نام متغیر را label_user_name بگذارید. اگر یک ویجت Entry برای دریافت سن کاربر دارید، می‌توانید آن را entry_age بنامید.

نکته: گاهی ممکن است ویجتی را بدون اختصاص دادن به متغیر جدید تعریف کنید و مستقیماً متد .pack() را روی همان خط فراخوانی نمایید:

این کار زمانی مفید است که قصد ندارید در ادامه به نمونه ویجت ارجاع دهید. در حالت معمول، پایتون این اشیای بدون متغیر را به دلیل مدیریت خودکار حافظه حذف می‌کند، اما Tkinter با ثبت داخلی هر ویجت جدید، از این کار جلوگیری می‌کند.

هنگامی که نام کلاس ویجت را در نام متغیر قرار می‌دهید، به خودتان و دیگران کمک می‌کنید تا بفهمند که متغیر مربوط به چه نوع ویجتی است. البته استفاده از نام کامل کلاس ویجت ممکن است باعث طولانی شدن نام‌ها شود. به همین دلیل، ممکن است بخواهید برای اشاره به هر نوع ویجت، از یک پیشوند کوتاه استفاده کنید.

در ادامه این آموزش، از پیشوندهای زیر برای نام گذاری ویجت ها استفاده خواهد شد:

کلاس ویجت پیشوند نام متغیر مثال
Label lbl lbl_name
Button btn btn_submit
Entry ent ent_age
Text txt txt_notes
Frame frm frm_address

در این بخش یاد گرفتید چگونه یک پنجره بسازید، از ویجت ها استفاده کنید، و با Frame ها کار کنید. در این مرحله، می‌توانید پنجره های ساده ای بسازید که پیام هایی را نمایش می‌دهند، اما هنوز یک اپلیکیشن کامل طراحی نکرده‌اید. در بخش بعدی، یاد خواهید گرفت که چطور با استفاده از مدیرهای چیدمان قدرتمند Tkinter، نحوه چیدمان ویجت ها در برنامه را کنترل کنید.

کنترل چیدمان با استفاده از مدیرهای چیدمان (Geometry Managers)

تا اینجا، شما ویجت ها را با استفاده از متد .pack() به پنجره ها و ویجت های Frame اضافه کرده‌اید، اما هنوز دقیقاً نمی‌دانید که این متد چه کاری انجام می‌دهد. بیایید این موضوع را روشن کنیم!

چیدمان برنامه ها در Tkinter با استفاده از چیزی به نام “مدیر چیدمان” (geometry manager) کنترل می‌شود. متد .pack() یکی از این مدیرها است، اما تنها گزینه موجود نیست. Tkinter دو مدیر چیدمان دیگر نیز دارد:

  • .place()

  • .grid()

هر پنجره یا Frame در برنامه شما فقط می‌تواند از یکی از این مدیرهای چیدمان استفاده کند. با این حال، فریم های مختلف می‌توانند مدیرهای چیدمان متفاوتی داشته باشند، حتی اگر در داخل فریمی قرار گرفته باشند که از مدیر چیدمان دیگری استفاده می‌کند.

ابتدا بیایید دقیق‌تر به .pack() نگاه کنیم.

مدیر چیدمان.pack()

مدیر چیدمان .pack() از یک الگوریتم بسته بندی برای قرار دادن ویجت ها در داخل یک Frame یا پنجره استفاده می‌کند، به ترتیبی که مشخص کرده‌اید. این الگوریتم برای هر ویجت دو مرحله اصلی دارد:

  1. محاسبه یک ناحیه مستطیل شکل به نام “بسته” (parcel) که به اندازه کافی بلند (یا عریض) است تا ویجت را در خود جای دهد و باقی مانده عرض (یا ارتفاع) پنجره را با فضای خالی پر می‌کند.

  2. قرار دادن ویجت در مرکز بسته، مگر این که مکان دیگری مشخص شده باشد.

.pack() قدرتمند است، اما تصور نحوه عملکرد آن ممکن است دشوار باشد. بهترین راه برای درک .pack() مشاهده مثال‌های عملی است. ببینید وقتی سه ویجت Frame را با استفاده از .pack() به یک پنجره اضافه می‌کنید چه اتفاقی می‌افتد:

.pack() به طور پیش‌فرض هر Frame را زیر مورد قبلی قرار می‌دهد، به ترتیبی که به پنجره اختصاص داده شده‌اند:

یک پنجره Tkinter با سه مربع رنگی که به صورت عمودی چیده شده‌اند

  • هر Frame در بالاترین موقعیت موجود قرار می‌گیرد. بنابراین ابتدا Frame قرمز در بالای پنجره قرار می‌گیرد، سپس Frame زرد در زیر آن، و در نهایت Frame آبی در پایین‌ترین موقعیت.

  • سه بسته نامرئی وجود دارند که هرکدام شامل یکی از این سه Frame هستند.

  • هر بسته به اندازه عرض پنجره عریض است و به اندازه ارتفاع Frame خودش بلند.

  • چون هنگام فراخوانی .pack() برای هر Frame هیچ موقعیت خاصی مشخص نشده، همه آن‌ها به طور پیش‌فرض در مرکز بسته خود قرار گرفته‌اند. به همین دلیل، هر Frame در مرکز پنجره قرار می‌گیرد.

استفاده از fill در .pack()

متد .pack() چند آرگومان کلیدی برای کنترل دقیق‌تر چیدمان ویجت ها دارد. برای مثال، می‌توانید از آرگومان fill استفاده کنید تا مشخص کنید ویجت در چه جهتی فضای باقی‌مانده را پر کند. گزینه های موجود:

  • tk.X برای پر کردن افقی

  • tk.Y برای پر کردن عمودی

  • tk.BOTH برای پر کردن در هر دو جهت

در مثال زیر، هر سه Frame طوری قرار داده می‌شوند که تمام عرض پنجره را پر کنند:

در اینجا هیچ مقدار widthای برای Frame ها تعیین نشده است، چون .pack(fill=tk.X) باعث می‌شود عرض هر Frame به طور خودکار با عرض پنجره برابر شود، حتی اگر عرض مشخصی تعیین شده باشد.

پنجره ای که توسط این اسکریپت تولید می‌شود به شکل زیر است:

یک پنجره Tkinter شامل سه قاب رنگی که به صورت عمودی چیده شده و به صورت افقی باز شده‌اند تا کل پنجره را پر کنند.

یکی از ویژگی‌های مثبت استفاده از .pack() برای پر کردن پنجره این است که خاصیت پر شدن (fill) نسبت به تغییر اندازه پنجره واکنش گرا (responsive) است. برای درک بهتر این موضوع، کافی است پنجره ای که توسط اسکریپت قبلی تولید شده را عریض تر کنید. با افزایش عرض پنجره، عرض هر سه ویجت Frame نیز افزایش می‌یابد تا کل عرض پنجره را پر کنند:

یک پنجره Tkinter که با تغییر اندازه پنجره، به صورت افقی گسترش می‌یابد

نکته: توجه کنید که این Frame ها فقط در جهت افقی بزرگ می‌شوند، نه عمودی.

استفاده از side در .pack()

آرگومان کلیدی دیگر در .pack()، side است که تعیین می‌کند ویجت در کدام سمت پنجره قرار بگیرد. گزینه‌های موجود:

  • tk.TOP

  • tk.BOTTOM

  • tk.LEFT

  • tk.RIGHT

اگر از side استفاده نکنید، .pack() به طور پیش‌فرض از tk.TOP استفاده می‌کند و ویجت ها را از بالا به پایین در پنجره قرار می‌دهد.

در مثال زیر، سه Frame به صورت افقی کنار هم از چپ به راست چیده می‌شوند و در جهت عمودی کل ارتفاع پنجره را پر می‌کنند:

در اینجا لازم است که برای حداقل یکی از Frame ها مقدار height را مشخص کنید تا پنجره ارتفاع داشته باشد.

نتیجه به این شکل خواهد بود:

یک پنجره Tkinter شامل سه قاب رنگی که به صورت افقی قرار گرفته و به صورت عمودی باز شده‌اند تا کل پنجره را پر کنند

درست همان‌طور که با تنظیم fill=tk.X باعث شدید فریم‌ها هنگام تغییر عرض پنجره به‌صورت افقی واکنش پذیر باشند، می‌توانید با استفاده از fill=tk.Y این واکنش پذیری را برای تغییر ارتفاع پنجره نیز فعال کنید.

یک پنجره Tkinter که با تغییر اندازه پنجره، به صورت عمودی گسترش می‌یابد

برای اینکه چیدمان واقعاً واکنش گرا (responsive) باشد، می‌توانید ابتدا اندازه اولیه‌ای برای فریم ها با استفاده از ویژگی های width و height مشخص کنید. سپس با استفاده از آرگومان کلیدی fill=tk.BOTH و همچنین تنظیم expand=True، فریم ها را طوری تنظیم کنید که به هر دو جهت گسترش پیدا کنند و فضای پنجره را به‌طور کامل و پویا پر کنند:

زمانی که اسکریپت بالا را اجرا می‌کنید، در ابتدا پنجره ای مشابه مثال قبلی مشاهده خواهید کرد. اما تفاوت اینجاست که حالا می‌توانید اندازه پنجره را به دلخواه تغییر دهید و هر سه فریم به‌صورت کاملاً واکنش گرا گسترش پیدا کرده و فضای موجود را پر خواهند کرد.

یک پنجره Tkinter که با تغییر اندازه پنجره، هم به صورت افقی و هم به صورت عمودی گسترش می‌یابد.

مدیریت چیدمان با .place() در Tkinter

با استفاده از متد .place() می‌توانید موقعیت دقیق یک ویجت (widget) را در داخل یک پنجره یا فریم مشخص کنید. برای این کار، باید دو آرگومان کلیدی x و y را تعیین کنید که به ترتیب مختصات افقی و عمودی گوشه‌ی بالا-چپ ویجت را مشخص می‌کنند. توجه داشته باشید که این مختصات بر حسب پیکسل هستند، نه بر حسب کاراکتر یا خطوط متنی.

در نظر داشته باشید که مبدأ مختصات (جایی که x و y هر دو صفر هستند)، گوشه‌ی بالا-چپ پنجره یا فریم است. بنابراین:

  • آرگومان x در متد .place() نشان‌دهنده‌ی تعداد پیکسل‌ها از لبه چپ پنجره یا فریم است.

  • آرگومان y نیز نشان‌دهنده‌ی تعداد پیکسل‌ها از لبه بالای پنجره یا فریم می‌باشد.

به‌عبارت دیگر، شما با استفاده از .place() می‌توانید دقیقاً مشخص کنید که یک ویجت در چه فاصله‌ای از بالا و چپ قرار بگیرد.

مثال از نحوه عملکرد .place():

شرح کد:

  1. در خط ۵ و ۶، یک فریم با اندازه‌ ۱۵۰ در ۱۵۰ پیکسل ایجاد شده و با استفاده از .pack() در پنجره قرار گرفته است.

  2. در خطوط ۸ و ۹، یک Label با متن و پس زمینه قرمز ساخته شده و در مختصات (۰، ۰) درون فریم قرار گرفته است.

  3. در خطوط ۱۱ و ۱۲، Label دوم با پس زمینه زرد در مختصات (۷۵، ۷۵) قرار می‌گیرد.

پنجره ای که کد تولید می‌کند به صورت زیر است:

یک پنجره Tkinter حاوی دو ویجت Label که با استفاده از .place()‎ طرح‌بندی شده‌اند.

توجه داشته باشید که اگر این کد را روی سیستم عامل متفاوتی اجرا کنید (مثلاً لینوکس، ویندوز یا مک)، که از فونت ها و استایل های متفاوتی استفاده می‌کند، ممکن است Label دوم (زردرنگ) تا حدی از لبه‌ پنجره بیرون بزند و دیده نشود به همین دلیل، متد .place() چندان مورد استفاده قرار نمی‌گیرد. علاوه بر این، این متد دو اشکال اصلی دارد:

  • مدیریت چیدمان با .place() می‌تواند دشوار باشد. این مشکل به ویژه زمانی که برنامه شما شامل تعداد زیادی ویجت (Widget) باشد، بیشتر نمایان می‌شود.
  • چیدمان های ایجاد شده با .place() واکنش گرا (Responsive) نیستند. این چیدمان ها با تغییر اندازه پنجره تغییر نمی‌کنند.

یکی از چالش‌های اصلی توسعه رابط کاربری گرافیکی (GUI) چندپلتفرمی، طراحی چیدمان هایی است که در هر پلتفرمی به‌خوبی نمایش داده شوند. متد .place() گزینه مناسبی برای ایجاد چیدمان های واکنش گرا و سازگار با پلتفرم های مختلف نیست.

با این حال، این به این معنا نیست که هرگز نباید از .place() استفاده کنید! در برخی موارد، این متد می‌تواند دقیقاً همان چیزی باشد که نیاز دارید. برای مثال، اگر در حال طراحی رابط کاربری گرافیکی برای یک نقشه هستید، .place() می‌تواند انتخابی ایده‌آل باشد تا ویجت ها در فاصله های دقیق و مناسب نسبت به یکدیگر روی نقشه قرار گیرند.

متد .pack() معمولاً گزینه بهتری نسبت به .place() است، اما حتی این متد نیز معایبی دارد. محل قرارگیری ویجت ها به ترتیب فراخوانی .pack() بستگی دارد، بنابراین اصلاح برنامه های موجود بدون درک کامل کد مربوط به چیدمان می‌تواند دشوار باشد. مدیر چیدمان .grid() بسیاری از این مشکلات را برطرف می‌کند، که در بخش بعدی به آن خواهیم پرداخت.

مدیریت چیدمان با .grid()

مدیر چیدمانی که احتمالاً بیشتر از همه از آن استفاده خواهید کرد، .grid() است. این روش تمام قابلیت‌های .pack() را دارد اما با ساختاری که درک و نگهداری آن آسان‌تر است.

.grid() با تقسیم کردن پنجره یا Frame به ردیف ها و ستون ها کار می‌کند. برای مشخص کردن محل قرارگیری یک ویجت، کافی است متد .grid() را فراخوانی کرده و شماره ردیف و ستون را به ترتیب از طریق آرگومان های row و column به آن بدهید. توجه داشته باشید که شماره گذاری ردیف ها و ستون ها از صفر شروع می‌شود. بنابراین، اگر مقدار row=1 و column=2 را بدهید، یعنی ویجت را در سومین ستون از دومین ردیف قرار دهید.

اسکریپت زیر یک جدول ۳×۳ از Frame ها ایجاد می‌کند که در هرکدام یک Label قرار داده شده است:

نتیجه به این شکل خواهد بود:

یک پنجره Tkinter حاوی یک شبکه ۳ در ۳ از ویجت‌های Frame به همراه ویجت‌های Label که درون آنها قرار گرفته‌اند

در این مثال، شما از دو «مدیر چیدمان» استفاده کرده‌اید. هر frame با استفاده از مدیر چیدمان .grid() به پنجره‌ اصلی (window) اضافه شده است:

هر label نیز با استفاده از .pack() به Frame مربوط به خودش متصل شده است:

نکته‌ مهمی که باید درک کنید این است که با وجود اینکه متد .grid() روی هر شی Frame فراخوانی می‌شود، اما مدیر چیدمان در واقع بر روی شی window اعمال می‌شود. به‌همین ترتیب، چیدمان درون هر frame با استفاده از مدیر چیدمان .pack() کنترل می‌شود.

در مثال قبلی، فریم ها دقیقاً در کنار یکدیگر قرار گرفته‌اند. برای اینکه مقداری فاصله بین فریم ها ایجاد کنید، می‌توانید برای هر خانه‌ جدول، padding (فضای خالی) تعیین کنید. Padding فقط فضای خالی‌ است که اطراف یک ویجت قرار می‌گیرد و محتوا را از نظر بصری متمایز می‌کند.

دو نوع padding وجود دارد: padding داخلی و padding خارجی. padding خارجی فضایی است که اطراف بیرونی یک سلول جدول اضافه می‌شود. این نوع padding با دو آرگومان کلیدی برای .grid() کنترل می‌شود:

  • padx فاصله افقی را اضافه می‌کند.

  • pady فاصله عمودی را اضافه می‌کند.

هر دو padx و pady برحسب پیکسل اندازه‌گیری می‌شوند، نه برحسب واحدهای متنی، بنابراین اگر مقدار یکسانی برای هر دو تنظیم کنید، به همان میزان در هر دو جهت فاصله ایجاد می‌شود.

سعی کنید مقداری padding به اطراف فریم ها در مثال قبلی اضافه کنید:

پنجره‌ حاصل به این صورت است:

یک پنجره Tkinter شامل یک شبکه ۳ در ۳ از ویجت‌های Frame به همراه ویجت‌های Label که در آنها قرار گرفته‌اند. هر سلول شبکه دارای ۵ پیکسل حاشیه خارجی است.

متد .pack() نیز دارای پارامترهای padx و pady است. کد زیر تقریباً با کد قبلی یکسان است، با این تفاوت که شما پنج پیکسل فضای خالی اضافی در اطراف هر Label، هم در جهت افقی و هم در جهت عمودی اضافه کرده‌اید:

فضای خالی اضافه شده در اطراف ویجت های Label باعث می‌شود که هر سلول در جدول کمی فضای تنفس بین حاشیه‌ Frame و متن داخل label داشته باشد:

یک پنجره Tkinter شامل یک شبکه ۳ در ۳ از ویجت‌های Frame به همراه ویجت‌های Label که در آنها قرار گرفته‌اند. هر سلول شبکه و ویجت Label دارای ۵ پیکسل فاصله خارجی هستند.

این ظاهر نسبتاً خوبی دارد! اما اگر تلاش کنید پنجره را در هر جهتی بزرگ تر کنید، متوجه خواهید شد که چیدمان چندان واکنش گرا (responsive) نیست:

یک پنجره Tkinter حاوی یک شبکه ۳ در ۳ که با تغییر اندازه پنجره گسترش نمی‌یابد

کل جدول همچنان در گوشه‌ بالا-چپ باقی می‌ماند حتی وقتی پنجره بزرگ تر می‌شود.

با استفاده از متدهای .columnconfigure() و .rowconfigure() روی شی window، می‌توانید مشخص کنید که ردیف ها و ستون های جدول هنگام تغییر اندازه پنجره چگونه رشد کنند. به خاطر داشته باشید که جدول به شی window متصل است، حتی اگر متد .grid() را روی هر ویجت Frame فراخوانی کرده باشید.

هر دو متد .columnconfigure() و .rowconfigure() سه آرگومان اساسی دریافت می‌کنند:

  • Index: شماره ای که نشان‌دهنده‌ اندیس ستون یا ردیفی است که می‌خواهید پیکربندی کنید (یا فهرستی از اندیس ها برای پیکربندی چند ردیف یا ستون به‌طور همزمان).

  • Weight: یک آرگومان کلیدی به نام weight که مشخص می‌کند ردیف یا ستون مورد نظر در مقایسه با سایر ردیف ها و ستون ها چگونه نسبت به تغییر اندازه پنجره واکنش نشان دهد.

  • Minimum Size: یک آرگومان کلیدی به نام minsize که حداقل اندازه ارتفاع ردیف یا عرض ستون را برحسب پیکسل تعیین می‌کند.

مقدار پیش‌فرض weight برابر ۰ است، به این معنا که ستون یا ردیف هنگام تغییر اندازه پنجره، رشد نمی‌کند. اگر به تمام ردیف ها یا ستون ها weight=1 بدهید، همه آن‌ها با نرخ یکسان رشد می‌کنند. اگر یک ستون weight=1 و دیگری weight=2 داشته باشد، ستون دوم دو برابر سریع‌تر از ستون اول رشد خواهد کرد.

در ادامه، اسکریپت قبلی را طوری تغییر دهید که بهتر با تغییر اندازه پنجره سازگار شود:

متدهای .columnconfigure() و .rowconfigure() در بدنه‌ حلقه‌ for بیرونی قرار گرفته‌اند. شما می‌توانید هر ستون و ردیف را به‌طور صریح و خارج از حلقه پیکربندی کنید، اما این کار نیاز به نوشتن شش خط کد اضافی دارد.

در هر تکرار از حلقه، ستون و ردیف با اندیس i طوری پیکربندی می‌شوند که وزن (weight) آن‌ها برابر با ۱ باشد. این موضوع تضمین می‌کند که ستون و ردیف با همان نرخ رشد کنند، هرگاه که اندازه پنجره تغییر کند. آرگومان minsize برای هر ستون برابر با ۷۵ و برای هر ردیف برابر با ۵۰ تنظیم شده است. این باعث می‌شود که ویجت Label همیشه متن خود را کامل نمایش دهد و هیچ کاراکتری حتی در کوچک ترین اندازه پنجره قطع نشود.

نتیجه، یک چیدمان جدولی (grid layout) است که هنگام تغییر اندازه‌ پنجره به‌صورت روان بزرگ و کوچک می‌شود:

یک پنجره Tkinter حاوی یک طرح شبکه‌ای کاملاً واکنش‌گرای ۳ در ۳

امتحان کنید تا نحوه عملکرد را بهتر درک کنید! با پارامترهای weight و minsize بازی کنید تا ببینید چگونه روی جدول تأثیر می‌گذارند.

به‌صورت پیش‌فرض، ویجت ها در مرکز خانه های جدول قرار می‌گیرند. به‌عنوان مثال، کد زیر دو ویجت Label ایجاد می‌کند و آن‌ها را در جدولی با یک ستون و دو ردیف قرار می‌دهد:

هر خانه‌ جدول دارای عرض ۲۵۰ پیکسل و ارتفاع ۱۰۰ پیکسل است. همان‌طور که در تصویر زیر مشخص است، Label‌ ها در مرکز هر سلول قرار دارند:

یک پنجره Tkinter با مدیریت چیدمان grid و اندازه‌های سطر و ستون سفارشی

شما می‌توانید مکان هر Label درون خانه جدول را با استفاده از پارامتر sticky تغییر دهید. این پارامتر رشته ای از یک یا چند حرف زیر را می‌پذیرد:

  • "n" یا "N" برای چسباندن به قسمت بالای وسط سلول (north)

  • "e" یا "E" برای چسباندن به سمت راست وسط سلول (east)

  • "s" یا "S" برای چسباندن به پایین وسط سلول (south)

  • "w" یا "W" برای چسباندن به سمت چپ وسط سلول (west)

حروف "n"، "s"، "e" و "w" برگرفته از جهات اصلی شمال، جنوب، شرق و غرب هستند. اگر در کد قبلی، پارامتر sticky را برای هر دو Label برابر "n" قرار دهید، هر Label در قسمت بالای وسط سلول خود قرار می‌گیرد.

خروجی کد به این صورت است:

یک پنجره Tkinter با مدیریت چیدمان grid و تنظیم sticky روی "شمال"

شما می‌توانید چند حرف را در یک رشته با هم ترکیب کنید تا Label‌ها را در گوشه های سلول های جدول قرار دهید:

در این مثال، پارامتر sticky برای label1 برابر با "ne" قرار داده شده است که باعث می‌شود لیبل در گوشه‌ بالا-راست سلول قرار گیرد. label2 نیز با مقدار "sw" در پایین-چپ سلول قرار می‌گیرد. شکل پنجره به این صورت خواهد بود:

یک پنجره Tkinter با مدیریت چیدمان grid و تنظیم Sticky روی «شمال شرقی» و «جنوب غربی»

زمانی که یک ویجت با استفاده از sticky جایگذاری می‌شود، اندازه‌ی خود ویجت فقط به‌اندازه ای خواهد بود که محتوای داخلی آن (مثل متن) را در خود جای دهد. یعنی ویجت کل سلول جدول را پر نمی‌کند. اگر می‌خواهید ویجت تمام فضای سلول را بپوشاند، می‌توانید از "ns" برای پر کردن سلول در جهت عمودی، یا "ew" برای پر کردن در جهت افقی استفاده کنید. برای پر کردن کامل سلول در هر دو جهت، sticky را روی "nsew" قرار دهید.

مثال زیر هر یک از این گزینه ها را نمایش می‌دهد:

نمای خروجی به‌صورت زیر خواهد بود:

یک پنجره Tkinter با مدیریت چیدمان grid و چسبنده که برای پر کردن افقی، عمودی و در امتداد هر دو محور استفاده می‌شود.

این مثال نشان می‌دهد که پارامتر sticky در .grid() می‌تواند همان کاری را انجام دهد که پارامتر fill در .pack() انجام می‌دهد. جدول زیر تطابق بین این دو را خلاصه می‌کند:

.grid() .pack()
sticky="ns" fill=tk.Y
sticky="ew" fill=tk.X
sticky="nsew" fill=tk.BOTH

.grid() یک مدیر چیدمان قدرتمند است. اغلب درک آن نسبت به .pack() ساده‌تر و نسبت به .place() بسیار انعطاف‌پذیرتر است. زمانی که در حال ساخت برنامه‌های جدید با Tkinter هستید، بهتر است از .grid() به‌عنوان مدیر چیدمان اصلی خود استفاده کنید.

نکته: .grid() انعطاف پذیری بسیار بیشتری نسبت به آنچه تا حالا دیدید دارد. به عنوان مثال، می‌توانید سلول هایی را تنظیم کنید که چند ردیف یا چند ستون را اشغال کنند. برای اطلاعات بیشتر، به بخش Grid Geometry Manager در آموزش TkDocs مراجعه کنید.

حالا که اصول اولیه‌ مدیران چیدمان (Geometry Managers) در فریم ورک گرافیکی Tkinter را یاد گرفتید، قدم بعدی این است که دکمه ها را طوری تنظیم کنید که با کلیک روی آن ها، عملیات خاصی در برنامه اجرا بشود.

تعاملی کردن برنامه ها در Tkinter 

تا این مرحله، با نحوه ایجاد یک پنجره در کتابخانه‌ Tkinter، افزودن ویجت ها و مدیریت چیدمان آن ها آشنا شده اید. این موارد، گام های مهمی در طراحی واسط کاربری به شمار می‌روند. با این حال، تنها زیبایی ظاهری کافی نیست؛ برنامه ها باید دارای عملکرد نیز باشند. در این بخش، با نحوه‌ زنده کردن برنامه های خود از طریق اجرای عملیات در پاسخ به رخدادهای مختلف آشنا خواهید شد.

استفاده از رویدادها و توابع پاسخ دهنده به رویداد (Event Handlers)

هنگامی که یک برنامه‌ Tkinter ایجاد می‌کنید، باید با فراخوانی window.mainloop()، حلقه‌ رویداد را آغاز نمایید. در طول اجرای این حلقه، برنامه به طور پیوسته بررسی می‌کند که آیا رویدادی اتفاق افتاده است یا خیر. در صورت وقوع یک رویداد، کدی که برای واکنش به آن نوشته‌اید اجرا خواهد شد.

حلقه‌ رویداد توسط خود Tkinter در اختیار شما قرار می‌گیرد و نیازی به نوشتن کدی برای بررسی رویدادها ندارید. با این حال، شما موظف هستید تابعی را بنویسید که در پاسخ به رویداد اجرا شود. در Tkinter، این توابع به عنوان «پاسخ‌دهنده به رویداد» یا event handler شناخته می‌شوند.

نکته: رویداد، هر کنشی است که در جریان حلقه‌ رویداد رخ می‌دهد و می‌تواند به اجرای رفتاری در برنامه منجر شود؛ مانند فشرده شدن کلید یا کلیک روی دکمه‌ ماوس.

هنگامی که یک رویداد رخ می‌دهد، شیئی از نوع رویداد ساخته می‌شود. این فرآیند توسط Tkinter انجام می‌شود و نیازی به ساخت دستی آن توسط برنامه‌نویس نیست.

در ادامه برای درک بهتر نحوه عملکرد حلقه‌ رویداد در Tkinter، یک حلقه‌ رویداد مفهومی را به صورت دستی پیاده سازی می‌کنیم. این کار به شما در درک بهتر مکانیزم داخلی Tkinter کمک خواهد کرد و مشخص می‌کند که کدام بخش ها باید توسط شما نوشته شوند.

فرض کنید لیستی به نام events وجود دارد که شامل اشیای رویداد است. هر بار که رویدادی در برنامه رخ دهد، به صورت خودکار یک شیء به این لیست افزوده می‌شود. شما مسئول پیاده سازی این مکانیسم نیستید؛ بلکه صرفاً باید نحوه‌ واکنش به رویدادها را تعریف نمایید. در مثال زیر، با استفاده از یک حلقه‌ بی‌نهایت می‌توان بررسی کرد که آیا رویدادی در لیست وجود دارد یا خیر:

در حال حاضر، حلقه‌ رویدادی که ایجاد کرده‌اید، هیچ واکنشی نسبت به اشیای رویداد (event) نشان نمی‌دهد. بیایید این رفتار را تغییر دهیم. فرض کنید برنامه‌ شما باید به فشرده شدن کلیدهای صفحه‌کلید پاسخ دهد. در این حالت، باید بررسی کنید که آیا رویداد موردنظر از نوع فشردن کلید (keypress) بوده است یا خیر. در صورت تأیید، باید شیء رویداد را به تابعی ارسال نمایید که برای مدیریت این نوع رویداد طراحی شده است.

در این سناریو فرض می‌کنیم شیء event دارای ویژگی .type باشد که مقدار آن، در صورت فشرده شدن یک کلید، برابر با رشته‌ی "keypress" خواهد بود. همچنین، ویژگی .char نیز وجود دارد که کاراکتر مربوط به کلید فشرده‌شده را در خود نگه می‌دارد.

در ادامه، یک تابع به نام handle_keypress() ایجاد می‌کنیم و کد مربوط به حلقه‌ رویداد را به‌روزرسانی می‌نماییم:

وقتی window.mainloop() را فراخوانی می‌کنید، چیزی شبیه به حلقه‌ بالا برای شما اجرا می‌شود. این متد دو بخش از حلقه را برای شما مدیریت می‌کند:

  • لیستی از رویدادهایی که رخ داده‌اند را نگهداری می‌کند.

  • هر زمان که یک رویداد جدید به این لیست اضافه شود، یک تابع مدیریت رویداد (event handler) را اجرا می‌کند.

حلقه‌ رویداد خود را به‌روزرسانی کنید تا به‌جای حلقه‌ دستی، از window.mainloop() استفاده کند:

.mainloop() کارهای زیادی را برای شما انجام می‌دهد، اما یک نکته در کد بالا جا افتاده است. چگونه Tkinter متوجه می‌شود که چه زمانی باید از handle_keypress() استفاده کند؟ ویجت‌های Tkinter متدی به نام .bind() دارند که دقیقاً برای همین منظور طراحی شده است.

استفاده از .bind()

برای فراخوانی یک تابع مدیریت رویداد (event handler) در هر بار وقوع یک رویداد روی یک ویجت، از متد .bind() استفاده می‌شود. گفته می‌شود که تابع مدیریت رویداد به رویداد «بسته شده» است، زیرا هر بار که رویداد رخ می‌دهد، این تابع فراخوانی می‌شود. در ادامه‌ مثال مربوط به فشردن کلید از بخش قبلی، از .bind() استفاده می‌کنید تا تابع handle_keypress() را به رویداد فشردن کلید متصل کنید:

در اینجا، تابع handle_keypress() با استفاده از window.bind() به رویداد "<Key>" متصل شده است. هر زمان که کلیدی در حین اجرای برنامه فشرده شود، برنامه نویسه‌ مربوط به آن کلید را چاپ خواهد کرد.

نکته: خروجی این برنامه در پنجره‌ رابط گرافیکی Tkinter چاپ نمی‌شود. این خروجی در جریان استاندارد خروجی (stdout) نمایش داده می‌شود.

اگر برنامه را در محیط IDLE اجرا کنید، خروجی در پنجره‌ تعاملی نمایش داده می‌شود. اگر برنامه را از طریق ترمینال اجرا نمایید، خروجی را در ترمینال مشاهده خواهید کرد.

متد .bind() همواره حداقل دو آرگومان دریافت می‌کند:

  • رویدادی که به‌صورت رشته ای به شکل "<event_name>" نمایش داده می‌شود. event_name می‌تواند هر یک از رویدادهای پشتیبانی شده توسط Tkinter باشد.

  • یک تابع مدیریت رویداد (event handler) که نام تابعی است که در هنگام وقوع رویداد فراخوانی خواهد شد.

تابع مدیریت رویداد به ویجتی متصل می‌شود که .bind() روی آن فراخوانی شده است. هنگامی که تابع مدیریت رویداد اجرا می‌شود، شیء رویداد به‌عنوان آرگومان به آن تابع ارسال می‌گردد.

در مثال بالا، تابع مدیریت رویداد به خود پنجره متصل شده بود. اما شما می‌توانید تابع مدیریت رویداد را به هر ویجتی در برنامه‌تان متصل کنید. برای مثال، می‌توانید یک تابع را به ویجت دکمه (Button) متصل نمایید تا در صورت کلیک روی دکمه، عملی انجام شود:

در این مثال، رویداد "<Button-1>" روی ویجت دکمه به تابع مدیریت رویداد handle_click متصل شده است. رویداد "<Button-1>" زمانی رخ می‌دهد که دکمه‌ چپ ماوس در حالی که نشانگر روی ویجت قرار دارد، فشرده شود. رویدادهای دیگری نیز برای کلیک ماوس وجود دارد، از جمله:

  • "<Button-2>" برای کلیک دکمه‌ میانی ماوس

  • "<Button-3>" برای کلیک دکمه‌ راست ماوس

نکته: برای مشاهده فهرستی از رویدادهای پرکاربرد، به بخش Event types در مستندات Tkinter نسخه‌ی ۸.۵ مراجعه کنید.

شما می‌توانید هر تابع مدیریت رویدادی را با استفاده از .bind() به هر نوع ویجتی متصل کنید، اما برای دکمه ها (Button)، روش ساده تری نیز وجود دارد و آن استفاده از ویژگی command در هنگام تعریف دکمه است.

استفاده از command

هر ویجت دکمه (Button) در Tkinter دارای ویژگی به نام command است که می‌توانید آن را به یک تابع نسبت دهید. هر زمان که دکمه فشرده شود، تابع مورد نظر اجرا خواهد شد.

به مثال زیر توجه کنید. ابتدا یک پنجره با یک ویجت Label ایجاد می‌کنید که یک مقدار عددی را نمایش می‌دهد. سپس دو دکمه در سمت چپ و راست این Label قرار می‌دهید. دکمه‌ سمت چپ برای کاهش مقدار و دکمه‌ سمت راست برای افزایش مقدار استفاده می‌شود.

در ادامه، کد مربوط به این پنجره آورده شده است:

پنجره به این شکل خواهد بود:

یک برنامه Tkinter با دکمه‌های افزایش و کاهش که یک شمارنده را افزایش و کاهش می‌دهند

اکنون که چیدمان برنامه تعریف شده است، می‌توانید با اختصاص دادن دستوراتی به دکمه ها، آن را تعاملی کنید. با دکمه‌ سمت چپ شروع می‌کنیم. هنگامی که این دکمه فشرده می‌شود، باید مقدار موجود در Label را یک واحد کاهش دهد. برای این منظور ابتدا باید به دو سؤال پاسخ داده شود:

  1. چگونه می‌توان متن موجود در Label را دریافت کرد؟

  2. چگونه می‌توان متن موجود در Label را به‌روزرسانی کرد؟

ویجت های Label متدی به نام .get() مانند ویجت های Entry یا Text ندارند. با این حال، می‌توانید متن آن‌ها را با استفاده از نحوه‌ نوشتار به سبک دیکشنری دریافت یا تنظیم کنید:

حال که می‌دانید چگونه متن Label را دریافت و تنظیم کنید، تابعی به نام increase() بنویسید که مقدار موجود در lbl_value را یک واحد افزایش دهد:

تابع increase() ابتدا متن موجود در lbl_value را دریافت کرده و آن را به عدد صحیح تبدیل می‌کند. سپس مقدار را یک واحد افزایش داده و متن Label را با مقدار جدید جایگزین می‌کند.

همچنین به تابعی به نام decrease() نیاز دارید تا مقدار موجود در lbl_value را یک واحد کاهش دهد:

توابع increase() و decrease() را درست پس از دستور import در کد خود قرار دهید.

برای اتصال دکمه ها به توابع، کافی است تابع مورد نظر را به ویژگی command دکمه اختصاص دهید. این کار را می‌توانید هنگام ایجاد دکمه ها انجام دهید. به عنوان مثال، دو خطی که دکمه ها را ایجاد می‌کنند، به شکل زیر به‌روزرسانی کنید:

همین کافی است تا دکمه ها را به توابع increase() و decrease() متصل کرده و برنامه را به یک برنامه کاربردی تبدیل کنید. تغییرات خود را ذخیره کرده و برنامه را اجرا کنید! با کلیک روی دکمه ها، مقدار عددی در وسط پنجره افزایش یا کاهش می‌یابد.

یک برنامه شمارنده ساخته شده با Tkinter

کد کامل برنامه برای شما در اینجا آمده است:

این برنامه شاید کاربرد خاصی نداشته باشد، اما مهارت‌هایی که در اینجا آموختید، در تمام برنامه هایی که خواهید ساخت کاربرد دارند:

  • از ویجت ها برای ایجاد اجزای رابط کاربری استفاده کنید.

  • از مدیرهای چیدمان (geometry managers) برای کنترل نحوه چیدمان اجزای برنامه بهره ببرید.

  • رویداد هایی (event handlers) بنویسید که با اجزای مختلف تعامل داشته باشند تا ورودی کاربر را دریافت و پردازش کنند.

در دو بخش بعدی، برنامه های کاربردی‌تری خواهید ساخت. ابتدا یک مبدل دما طراحی می‌کنید که مقدار دما را از فارنهایت به سلسیوس تبدیل می‌کند. پس از آن، یک ویرایشگر متن خواهید ساخت که امکان باز کردن، ویرایش و ذخیره فایل های متنی را فراهم می‌کند.

آیا مایلید همین حالا با پروژه مبدل دما شروع کنیم؟

ساخت یک مبدل دما

در این بخش، یک اپلیکیشن ساده برای تبدیل دما می‌سازید. این برنامه به کاربر اجازه می‌دهد که مقدار دما را بر حسب درجه فارنهایت وارد کرده و با فشردن یک دکمه، آن را به درجه سلسیوس (سانتی‌گراد) تبدیل کند. مراحل کدنویسی این برنامه را مرحله به مرحله بررسی خواهیم کرد. در پایان این بخش نیز می‌توانید نسخه کامل کد را مشاهده کنید.

نکته: برای بهره‌مندی بهتر از این آموزش، توصیه می‌شود مراحل را در محیط Python اجرا کنید.

پیش از شروع کدنویسی، ابتدا رابط کاربری اپلیکیشن را طراحی می‌کنیم. به سه عنصر اصلی نیاز داریم:

  • Entry: یک ویجت با نام ent_temperature برای وارد کردن مقدار فارنهایت

  • Label: یک ویجت با نام lbl_result برای نمایش نتیجه تبدیل‌شده به سلسیوس

  • Button: یک ویجت با نام btn_convert که هنگام کلیک، مقدار را از Entry می‌خواند، آن را تبدیل کرده و متن Label را به نتیجه تبدیل‌شده تغییر می‌دهد

این اجزا را می‌توانید به صورت یک سطر و سه ستون در یک جدول (Grid) قرار دهید. البته برای کاربرپسند بودن، بهتر است هرکدام برچسب مناسبی داشته باشند.

برای مثال، کنار ویجت ent_temperature یک برچسب قرار می‌دهید که علامت فارنهایت (℉) را نشان دهد تا مشخص شود مقدار ورودی باید به فارنهایت باشد. برای این کار، متن برچسب را برابر با "\N{DEGREE FAHRENHEIT}" قرار می‌دهید که از قابلیت Unicode در پایتون برای نمایش این علامت استفاده می‌کند.

برای زیباتر شدن دکمه تبدیل، می‌توانید متن آن را برابر "\N{RIGHTWARDS BLACK ARROW}" بگذارید که یک فلش سیاه به سمت راست نمایش می‌دهد. همچنین مطمئن می‌شوید که برچسب lbl_result همیشه شامل علامت سلسیوس (℃) پس از متن نتیجه باشد. برای این منظور، از "\N{DEGREE CELSIUS}" استفاده می‌کنید.

در پایان، ظاهر نهایی پنجره به صورت زیر خواهد بود:

یک برنامه تبدیل دما ساخته شده با Tkinter

حالا که می‌دانید به چه ویجت هایی نیاز دارید و ظاهر پنجره چگونه خواهد بود، می‌توانید کدنویسی برنامه را آغاز کنید! ابتدا ماژول tkinter را وارد کرده و یک پنجره جدید ایجاد کنید:

تابع window.title() عنوان پنجره را روی «Temperature Converter» قرار می‌دهد. همچنین، با window.resizable(False, False) اندازه پنجره ثابت می‌ماند و قابل تغییر توسط کاربر نخواهد بود.

در مرحله بعد، ویجت ent_temperature را برای ورود مقدار دما تعریف می‌کنیم. برای مشخص کردن اینکه این مقدار بر حسب فارنهایت است، یک برچسب به نام lbl_temp در کنار آن قرار می‌دهیم. این دو ویجت را در یک Frame به نام frm_entry قرار می‌دهیم تا گروه‌بندی شوند:

کاربر مقدار دمای مورد نظر را در ent_temperature وارد می‌کند و برچسب lbl_temp به‌وضوح نشان می‌دهد که این مقدار بر حسب فارنهایت است.

برای اینکه lbl_temp دقیقاً در سمت راست ent_temperature قرار گیرد، از مدیریت موقعیت .grid() استفاده می‌کنیم و هر ویجت را در یک ستون جداگانه از یک سطر قرار می‌دهیم:

پارامتر sticky="e" باعث می‌شود که ent_temperature به لبه راست سلول خود بچسبد، و sticky="w" برای lbl_temp باعث می‌شود که به لبه چپ سلول خود بچسبد. این تنظیمات تضمین می‌کند که این دو ویجت در کنار هم و منظم قرار بگیرند.

اکنون نوبت ساخت دکمه btn_convert برای تبدیل دما و برچسب lbl_result برای نمایش نتیجه است:

درست مانند frm_entry، دو ویجت btn_convert و lbl_result نیز مستقیماً به پنجره اصلی (window) متصل می‌شوند. این سه ویجت در مجموع، سه سلول اصلی از جدول (grid) رابط کاربری شما را تشکیل می‌دهند. حالا با استفاده از متد .grid() آن‌ها را در پنجره قرار دهید:
در پایان، اجرای برنامه را با فراخوانی window.mainloop() آغاز کنید:
همه‌چیز عالی به نظر می‌رسد! اما هنوز دکمه عملکردی ندارد. برای فعال کردن عملکرد آن، درست در بالای فایل اسکریپت و بلافاصله بعد از خط import، یک تابع به نام fahrenheit_to_celsius() اضافه کنید.

این تابع مقدار واردشده در ent_temperature را می‌خواند، آن را از فارنهایت به سلسیوس تبدیل می‌کند و سپس نتیجه را در lbl_result نمایش می‌دهد.

در ادامه، به خطی که دکمه btn_convert را تعریف کرده‌اید بروید و ویژگی command آن را برابر با تابع fahrenheit_to_celsius قرار دهید:

همین! شما با موفقیت یک برنامه مبدل دمای کامل را تنها در ۲۶ خط کد ساخته‌اید! جالب است، نه؟

می‌توانید کد کامل برنامه را در زیر ببینید:

حالا میتوانیم برویم سراغ ساخت یک ویرایشگر متن! آماده‌اید؟

ساخت ویرایشگر متن

در این بخش، یک برنامه ویرایشگر متن طراحی می‌کنید که می‌تواند فایل های متنی را ایجاد، باز، ویرایش و ذخیره کند. این برنامه شامل سه عنصر اصلی است:

  • یک ویجت دکمه (Button) به نام btn_open برای باز کردن فایل جهت ویرایش

  • یک ویجت دکمه (Button) به نام btn_save برای ذخیره سازی فایل

  • یک ویجت جعبه متن (TextBox) به نام txt_edit برای ایجاد و ویرایش محتوای فایل

نحوه چیدمان این سه ویجت به این صورت است:
دو دکمه در سمت چپ پنجره قرار می‌گیرند، و جعبه متن در سمت راست پنجره. کل پنجره باید حداقل ارتفاع ۸۰۰ پیکسل داشته باشد، و txt_edit نیز باید حداقل عرض ۸۰۰ پیکسل را داشته باشد.

نکته مهم: طراحی باید واکنش گرا (responsive) باشد. یعنی اگر کاربر پنجره را تغییر اندازه دهد، تنها txt_edit تغییر اندازه دهد، نه قاب دکمه ها. عرض قاب دکمه ها باید ثابت باقی بماند.

در ادامه طرح کلی ظاهر این برنامه آمده است:

طرح اولیه برای یک برنامه ویرایشگر متن

برای رسیدن به چیدمان موردنظر، می‌توانید از مدیر چیدمان .grid() استفاده کنید. این چیدمان شامل یک ردیف و دو ستون است:

  • ستونی باریک در سمت چپ برای دکمه ها

  • ستونی پهن تر در سمت راست برای جعبه متن (txt_edit)

برای اینکه پنجره و txt_edit حداقل اندازه ۸۰۰ پیکسل داشته باشند، می‌توانید از متدهای .rowconfigure() و .columnconfigure() روی پنجره استفاده کنید و پارامتر minsize را برابر ۸۰۰ قرار دهید. همچنین برای اینکه txt_edit با تغییر اندازه پنجره، تغییر اندازه دهد (واکنش گرا باشد)، باید پارامتر weight را روی ۱ تنظیم کنید.

برای قرار دادن دکمه ها در یک ستون، نیاز دارید که یک ویجت فریم (Frame) به نام frm_buttons بسازید. طبق طرح شماتیک، دو دکمه باید به‌صورت عمودی در این قاب قرار بگیرند، به‌طوری‌که btn_open در بالا باشد. برای این کار، می‌توانید از .grid() یا .pack() استفاده کنید. در حال حاضر، از .grid() استفاده می‌کنیم چون کار با آن آسان‌تر است و کنترل بیشتری می‌دهد.

حالا که برنامه‌ریزی انجام شد، می‌توانیم کدنویسی برنامه را آغاز کنیم. اولین گام، ایجاد تمام ویجت های موردنیاز است.

در اینجا شرحی از کد آمده است:

  • خط ۱: کتابخانه tkinter را وارد می‌کند.

  • خطوط ۳ و ۴: یک پنجره جدید ایجاد کرده و عنوان آن را “Simple Text Editor” می‌گذارند.

  • خطوط ۶ و ۷: تنظیمات مربوط به ردیف و ستون پنجره را انجام می‌دهند.

  • خطوط ۹ تا ۱۲: چهار ویجتی که لازم دارید ایجاد می‌کنند: یک جعبه متن (txt_edit)، یک فریم (frm_buttons) و دو دکمه باز کردن (btn_open) و ذخیره کردن (btn_save).

بررسی دقیق‌تر خط ۶:

  • آرگومان اول 0 مشخص می‌کند که این تنظیمات برای اولین ردیف اعمال شود.

  • minsize=800 یعنی حداقل ارتفاع این ردیف ۸۰۰ پیکسل خواهد بود.

  • weight=1 باعث می‌شود این ردیف نسبت به تغییر اندازه پنجره، مقیاس‌پذیر باشد.

از آنجا که تنها یک ردیف در این رابط کاربری وجود دارد، این تنظیمات به کل پنجره اعمال می‌شوند.

بررسی دقیق‌تر خط ۷:

در این خط از .columnconfigure() استفاده شده است تا برای ستون شماره ۱ (ستونی که txt_edit در آن قرار می‌گیرد) تنظیماتی انجام شود:

  • minsize=800 تضمین می‌کند که حداقل عرض ستون دوم (ستونی که حاوی جعبه متن است)، ۸۰۰ پیکسل باشد.

  • weight=1 باعث می‌شود این ستون نیز با تغییر اندازه پنجره، به صورت خودکار تغییر اندازه دهد.

به این ترتیب، فقط جعبه متن (نه دکمه ها) به صورت واکنش گرا رفتار خواهد کرد.

به یاد داشته باشید که اندیس های ردیف و ستون در tkinter از صفر شروع می‌شوند؛ بنابراین تنظیماتی که برای ستون شماره ۱ انجام دادید، فقط به دومین ستون (یعنی ستونی که جعبه متن در آن قرار دارد) اعمال می‌شود. از آنجا که فقط این ستون واکنش گرا شده، هنگام تغییر اندازه پنجره، فقط جعبه متن به‌صورت پویا بزرگ و کوچک می‌شود، در حالی که ستونی که دکمه ها در آن هستند عرض ثابتی خواهد داشت.

حالا می‌توانید روی چیدمان عناصر در اپلیکیشن کار کنید. ابتدا، دکمه ها را با استفاده از مدیریت چیدمان .grid() داخل فریم frm_buttons قرار دهید:

توضیح کد:

  • این دو خط یک شبکه ۲ ردیفی و ۱ ستونی در قاب frm_buttons ایجاد می‌کنند.

  • btn_open در ردیف ۰ و btn_save در ردیف ۱ قرار می‌گیرد، بنابراین دکمه “باز کردن فایل” بالاتر از دکمه “ذخیره فایل” نمایش داده می‌شود، دقیقاً همان‌طور که در طرح اولیه پیش‌بینی کرده بودید.

  • ویژگی sticky="ew" باعث می‌شود هر دکمه در جهت افقی (از شرق تا غرب) کشیده شود و کل عرض ستون را پر کند.

  • padx و pady برای ایجاد فاصله داخلی در اطراف دکمه ها استفاده می‌شوند تا ظاهری مرتب‌تر داشته باشند.

در مرحله بعد، باید frm_buttons و txt_edit را در پنجره اصلی قرار دهید.

شما با تنظیم مقادیر padx و pady برابر با ۵، به هر دکمه پنج پیکسل فاصله داخلی (padding) از اطراف اختصاص می‌دهید. فقط دکمه btn_open دارای فاصله عمودی (pady) است. از آنجا که این دکمه در بالای پنجره قرار دارد، این فاصله عمودی باعث می‌شود کمی از بالای پنجره پایین‌تر قرار بگیرد و در نتیجه فاصله کوچکی بین آن و دکمه btn_save ایجاد شود.

حالا که بخش frm_buttons (فریم دکمه ها) چیدمان شده و آماده است، می‌توانید چیدمان شبکه‌ای (grid layout) بقیه پنجره را تنظیم کنید:

این دو خط کد یک شبکه با یک ردیف و دو ستون در پنجره ایجاد می‌کنند. بخش frm_buttons را در ستون اول و txt_edit را در ستون دوم قرار می‌دهید، بنابراین در چیدمان پنجره، frm_buttons در سمت چپ txt_edit نمایش داده می‌شود.

پارامتر sticky برای frm_buttons روی "ns" تنظیم شده که باعث می‌شود این قاب به صورت عمودی کشیده شود و تمام ارتفاع ستون خود را پر کند. ویجت txt_edit نیز با استفاده از پارامتر sticky="nsew" در تمام جهات کشیده می‌شود و کل فضای اختصاص‌یافته در سلول شبکه اش را پر می‌کند.

اکنون که چیدمان رابط کاربری کامل شده است، دستور window.mainloop() را در انتهای برنامه اضافه کرده، فایل را ذخیره کرده و اجرا کنید:

پنجره زیر نمایش داده می‌شود:

یک برنامه ویرایشگر متن ساخته شده با Tkinter

این عالی به نظر می‌رسد! اما در حال حاضر هیچ عملکردی ندارد، بنابراین باید شروع به نوشتن دستورات مربوط به دکمه ها کنید. دکمه btn_open باید یک پنجره انتخاب فایل (File Open Dialog) نمایش دهد و به کاربر اجازه دهد یک فایل را انتخاب کند. سپس باید آن فایل را باز کند و محتوای آن را در ناحیه متنی txt_edit نمایش دهد. تابع open_file() زیر دقیقاً همین کار را انجام می‌دهد:

در ادامه، شرح خط به خط عملکرد این تابع آمده است:

  • خطوط ۷–۵: از تابع askopenfilename() که در ماژول tkinter.filedialog قرار دارد، برای نمایش پنجره انتخاب فایل استفاده می‌شود. مسیر فایلی که کاربر انتخاب می‌کند، در متغیر filepath ذخیره می‌شود.

  • خطوط ۸ و ۹: بررسی می‌شود که آیا کاربر پنجره را بسته یا روی دکمه “لغو” (Cancel) کلیک کرده است. در این صورت مقدار filepath خالی خواهد بود و تابع بدون انجام هیچ کاری بازمی‌گردد.

  • خط ۱۰: محتوای فعلی txt_edit با استفاده از متد .delete() پاک می‌شود.

  • خطوط ۱۱ و ۱۲: فایل انتخاب‌شده باز شده و محتوای آن با استفاده از متد .read() خوانده و به صورت یک رشته در متغیر text ذخیره می‌شود.

  • خط ۱۳: رشته متنی text با متد .insert() در ناحیه متنی txt_edit قرار داده می‌شود.

  • خط ۱۴: عنوان پنجره به‌روزرسانی می‌شود تا مسیر فایل باز شده در آن نمایش داده شود.

اکنون می‌توانید برنامه را طوری به‌روزرسانی کنید که دکمه btn_open هنگام کلیک، تابع open_file() را اجرا کند. برای این کار، ابتدا باید تابع askopenfilename() را از ماژول tkinter.filedialog وارد (import) کنید. بنابراین خط زیر را به ابتدای برنامه اضافه کنید:

سپس، ویژگی دستور btn_opn را روی open_file تنظیم کنید:

فایل را ذخیره کرده و آن را اجرا کنید تا مطمئن شوید همه چیز درست کار می‌کند. سپس یک فایل متنی را باز کنید تا نتیجه را ببینید!

اکنون که دکمه btn_open به‌درستی عمل می‌کند، نوبت به پیاده سازی تابع مربوط به دکمه btn_save رسیده است. این دکمه باید یک پنجره ذخیره فایل نمایش دهد تا کاربر بتواند محل و نام فایل خروجی را انتخاب کند. برای این کار، از تابع asksaveasfilename() در ماژول tkinter.filedialog استفاده خواهید کرد.

این تابع همچنین باید محتوای موجود در txt_edit را استخراج کرده و آن را در فایل انتخاب شده توسط کاربر ذخیره کند. تابع زیر دقیقاً همین کار را انجام می‌دهد:

در ادامه، شرح عملکرد این کد آورده شده است:

  • خطوط ۲۲–۱۹: پنجره ذخیره فایل با استفاده از تابع asksaveasfilename() باز می‌شود تا مسیر مورد نظر برای ذخیره فایل را از کاربر دریافت کند. مسیر انتخاب شده در متغیر filepath ذخیره می‌شود.

  • خطوط ۲۳ و ۲۴: بررسی می‌شود که آیا کاربر پنجره را بسته یا دکمه “لغو” (Cancel) را زده است. در این صورت، filepath خالی خواهد بود و تابع بدون انجام عملیات ذخیره، به پایان می‌رسد.

  • خط ۲۵: فایل جدیدی در مسیر انتخاب‌شده ایجاد می‌شود.

  • خط ۲۶: محتوای ناحیه متنی txt_edit با استفاده از متد .get() استخراج شده و در متغیر text ذخیره می‌شود.

  • خط ۲۷: متن استخراج شده در فایل خروجی نوشته می‌شود.

  • خط ۲۸: عنوان پنجره به‌روزرسانی می‌شود تا مسیر فایل ذخیره‌شده در آن نمایش داده شود.

اکنون می‌توانید برنامه را به‌روزرسانی کنید تا دکمه btn_save هنگام کلیک، تابع save_file() را اجرا کند. برای انجام این کار، چند مرحله را باید طی کنید.

ابتدا باید تابع asksaveasfilename() را از ماژول tkinter.filedialog وارد (import) کنید. برای این کار، بخش import در ابتدای اسکریپت را به شکل زیر به‌روزرسانی کنید:

سپس، ویژگی (attribute) command دکمه btn_save را طوری تنظیم کنید که هنگام کلیک، تابع save_file() فراخوانی شود:

فایل را ذخیره کرده و اجرا کنید. اکنون شما یک ویرایشگر متن ساده اما کاملاً کاربردی در اختیار دارید!

در صورت تمایل، می‌توانید بخش کد کامل برنامه را در زیر مشاهده کنید تا تصویر جامع‌تری از آن داشته باشید:

شما تا اینجا دو برنامه گرافیکی (GUI) با استفاده از زبان برنامه نویسی پایتون ساخته‌اید و بسیاری از مهارت‌هایی را که در طول این آموزش آموخته‌اید، به‌کار گرفته‌اید. این دستاورد کمی نیست، بنابراین به خودتان افتخار کنید و زمانی را برای لذت بردن از پیشرفت‌تان اختصاص دهید. حالا آماده‌اید تا به‌تنهایی سراغ پروژه های جدید و هیجان‌انگیز بروید!

نتیجه گیری

در این آموزش، با برنامه نویسی رابط کاربری گرافیکی (GUI) در پایتون آشنا شدید. کتابخانه Tkinter یکی از گزینه های مناسب برای ساخت رابط گرافیکی در پایتون است، زیرا به‌صورت پیش‌فرض در کتابخانه استاندارد پایتون وجود دارد و ساخت برنامه ها با آن نسبتاً ساده و بدون دردسر است.

در طول این آموزش، با چند مفهوم کلیدی در Tkinter آشنا شدید:

  • نحوه کار با ابزارهای گرافیکی (ویجت ها)

  • مدیریت چیدمان اجزای برنامه با استفاده از مدیرهای چیدمان (Geometry Managers)

  • ایجاد تعامل و پاسخ‌دهی برنامه به ورودی های کاربر

  • استفاده از پنج ویجت پایه Tkinter شامل: Label (برچسب)، Button (دکمه)، Entry (ورودی تک خطی)، Text (ورودی چند خطی) و Frame (فریم)

اکنون که اصول اولیه ساخت رابط گرافیکی با Tkinter را یاد گرفته‌اید، قدم بعدی این است که پروژه های اختصاصی خودتان را بسازید و تمرین کنید. چه چیزی خلق خواهید کرد؟ پروژه های سرگرم‌کننده خود را در بخش نظرات به اشتراک بگذارید!

سوالات متداول

اکنون که با برنامه نویسی رابط گرافیکی (GUI) در پایتون با استفاده از Tkinter آشنا شده‌اید، می‌توانید با مرور سوالات زیر، درک خود را محک بزنید و آموخته هایتان را مرور کنید.

این سوالات متداول به مهم‌ترین مفاهیمی مربوط می‌شوند که در این آموزش با آن‌ها سروکار داشته‌اید.

Tkinter در پایتون چیست و چرا استفاده می‌شود؟

Tkinter ابزار استاندارد ساخت رابط گرافیکی (GUI) در پایتون است که در کتابخانه استاندارد پایتون وجود دارد. این ابزار به شما اجازه می‌دهد برنامه های گرافیکی طراحی کنید که روی سیستم عامل های مختلف مانند ویندوز، مک و لینوکس اجرا شوند. Tkinter امکان ساخت عناصر رابط کاربری مانند دکمه ها، جعبه های متن و منو ها را فراهم می‌کند.

چگونه می‌توان با استفاده از Tkinter یک پنجره ساده ایجاد کرد؟

برای ساخت یک پنجره ابتدایی در Tkinter، ابتدا باید ماژول tkinter را import کنید، سپس یک نمونه از کلاس Tk بسازید و در نهایت متد mainloop() را فراخوانی کنید. این متد، حلقه رویدادها (event loop) را آغاز می‌کند و باعث می‌شود پنجره باز بماند تا زمانی که کاربر آن را ببندد.

مدیرهای چیدمان (Geometry Managers) در Tkinter چه هستند و چگونه کار می‌کنند؟

مدیرهای چیدمان مسئول کنترل نحوه قرارگیری ویجت ها (widgets) در پنجره هستند. سه مدیر اصلی چیدمان در Tkinter عبارت‌اند از:

  • .pack() که ویجت ها را به‌صورت بلوکی در پنجره والد قرار می‌دهد.

  • .grid() که ویجت ها را در قالب جدول، با استفاده از ردیف (row) و ستون (column) جای می‌دهد.

  • .place() که ویجت ها را در مکان دقیق و با مختصات مشخص‌شده قرار می‌دهد.

چگونه می‌توان یک برنامه Tkinter را تعاملی کرد؟

برای ایجاد تعامل در برنامه های Tkinter، باید رویدادها (events) را به ویجت ها متصل کنید. برای دکمه ها معمولاً از ویژگی command استفاده می‌شود تا با کلیک کاربر، یک تابع اجرا شود. برای دیگر رویدادها مانند فشردن کلید یا کلیک ماوس می‌توان از متد .bind() استفاده کرد.

برخی از ویجت های رایج در برنامه های Tkinter کدام‌اند؟

  • Label: برای نمایش متن یا تصویر

  • Button: دکمه ای که با کلیک کاربر می‌تواند یک تابع را اجرا کند

  • Entry: برای دریافت ورودی متنی یک خطی از کاربر

  • Text: برای دریافت یا نمایش متن چند خطی

  • Frame: برای گروه بندی و سازماندهی سایر ویجت ها در یک بخش مجزا از پنجره

به این مطلب امتیاز دهید

راستی! برای دریافت مطالب جدید در کانال تلگرام یا پیج اینستاگرام سورس باران عضو شوید.

دوره آموزش طراحی فروشگاه اینترنتی بدون کد نویسی در 8 ساعت

دسته بندی موضوعات

آخرین محصولات فروشگاه

مشاهده همه

نظرات

بازخوردهای خود را برای ما ارسال کنید