سلام!
مقدمه ای که به نظرم خوندنش خالی از لطف نیست ، ولی اگه حوصله نداری میتونی ردش کنی!
داشتم توی محتوا های جادی می گشتم که به یه سریویدئو ی جالب بخوردم : « بستون » . توی این سری فیلم جادی شروع کرده بود به ساختن یه چیزی شبیه پلتفرم ثبت و رصد مخارج و درآمد هاش با پایتون ، نکته این بود که از تمام مراحل هم فیلم گرفته بود ! از خراب شدنش ، از سرچ کردن هاش و خلاصه از همه چیز ...
این شد که گفتم خب چه حرکت جالبی! من که خب قطعا به اندازه ی جادی مهارت ندارم ، ویدئو ضبط کن هم که نیستم ، چهکنم چهکار کنم؟
برم از مراحل یه پروژه قدم به قدم بنویسم . سنگ مفت ، گنجشک هم مفت! یا خوب میشه که چه عالی ! یا بد میشه که اصلا مهم نیست :|
حالا فقط میموند که چی باشه؟
دقت کردید به notepad و gedit ؟ به فرقشون توجه کنید ... gedit رو حتی میشه یجور code editor ابتدایی دونست ، اما نوت پد ؟! نوت پد چی؟ خب نمیدونم notepadدقیقا چیه 🤣 ولی خب در این حد میشه گفت « یه چیزیه که نهایتا حالت تاریک و روشن داره و میشه توش چیز میز نوشت ، بعدم با همه ی فرمت ها ذخیرهش کرد :| » . ایده اینه که یه چیزی بسازیم ، بهتر از notepad ، شبیه gedit و ضعیف تر از notepad++ .
مقدمه ی اصلی ( بخونید که بدونید چه خبره )
خب ، اگه مقدمه ی نسبتا طولانی بالا رو نخوندید ( که بهتون حق میدم ) ، خلاصه ی کاری که میخوایم بکنیم اینه که قدم به قدم یه نسخه ی بهتر از notepad رو ، با پایتون بسازیم .
نکته هم اینه که « من قبلا این کار رو نکردم ، در نتیجه امکان داره وسط کار خراب بشه و کلا بنیاد کار رو عوض کنیم » اما چیزی که بهتون اطمینان میدم اینه که چیز های خیلی خیلی خوبی رو یاد خواهیم گرفت . در نتیجه حتی اگه پروژه کلا شکست هم بخوره باز برای شما ی خواننده اتفاق بدی نیفتاده ، این وسط ها کلی کار هست که باید بکنیم و از هر کدومشون هم چیز های خوبی میتونه دربیاد ( البته به نظر خودم ) .
مقدمه بسه ، بریم شروع کنیم .
چی میخوایم؟
فعلا ابزار هایی که احتیاج داریم این ها هستن (غیر از پایتون 😁) :
- PySimpleGUI - برای نوشتن UI
- subprocess - برای کامپایل کردن و این جور کارا ( که احتمالا برای چند تا زبان یه همچین قابلیتی رو بذاریم
فعلا در همین حد به نظم کافیه ، تا بعد ببینیم چی به کارمون میاد .
subprocess که پیشفرض پایتونه اما PySimpleGUI رو باید نصب کنید . خیلی بعیده ندونه کسی ، ولی خب برای احتیاط مینویسم :
windows :
pip install PySimpleGUI
linux :
!pip install PySimpleGUI
دلیل استفاده مون از PySimpleGUI کیفیت بیشتر و امکانات بهترش نسبت به tkinter و سادگیش نسبت به پایکیوت و پایسایده
استارت
خب ، بریم که شروع کنیم .
اول از همه بریم ابتدایی ترین عضو برنامه رو داشته باشیم . پنجره ی برنامه .
import PySimpleGui as gui
window = gui.Window("title",[layout] , (size))
این یه طرح کلی از چیزی که میخوایمه. اول از همه که خب داریم یه آبجکتی به اسم window میسازیم . همونطور که از اسمش برمیاد ، این همون پنجره ی برنامهس .
کلاسِ Window که ما ازش یه آبجکت ساختیم ، یه تابع سازنده ( init ) داره که (غیر از self) چند تا آرگومان رو باید دریافت کنه .
ما از بین این آرگومان ها ، سه تاشون رو در حال حاضر احتیاج داریم که title ، layout و size هستن . هر کدوم هم قاعدتا یه چیزی رو تعیین می کنن .
- title -> اسمی که قراره بالای پنجره بیاد
- size -> اندازه ی پنجره
- layout -> اجزای برنامه که داخل window هستن
- مِنو ها ، باتن ها و هر چیزی
با این حساب همچین چیزی رو باید داشته باشیم ( به جای قبلی )
import PySimpleGui as gui
window = gui.Window("notepad+",[layout] , siza = (500,500))
چرا layout رو خالی گذاشتم؟ دلیلش اینه که یه لیستِ تقریبا بزرگه . ما هم میخوایم که تمیز و با دقت کد بزنیم . عقل حکم می کنه یه لیست جداگانه ایجاد کنیم و اونجا محتویات برنامه رو بنویسیم بعدم به عنوان آرگومان ، اونجا واردش کنیم .
فعلا توی برنامهمون چی میخوایم؟ یه جایی که توش متن رو بشه وارد کرد . کلاسِ Multiline برامون این فضا رو فراهم میکنه . آرگومان هایی که ازمون میخواد مربوط میشن به اندازه و فونت ؛ البته آرگومان های دیگه هم هست که الان کاریشون نداریم ، ولی بعدا حتما استفاده خواهیم کرد . تا الان باید همچین چیزی داشته باشـیم :
import PySimpleGui as gui
layout = [
[gui.Multiline( font=("courier", 12) , size=(80, 55) )]
]
#...
سوال : چرا انقدر tuple و list در list شد؟!
پاسخ : tuple که تایپِ آرگومانیِ که دریافت میکنه . اینکه چرا انقدر list لازمه رو هم از کسی بپرسید که کتابخونه رو نوشته :)
بعله ...
تا اینجا ما یه پنجره داریم و یه جایی برای نوشتن متن .
پس مینویسیم که :
import PySimpleGui as gui
layout = [
[gui.Multiline( font=("courier", 12) , size=(80, 55) )]
]
window = gui.Window("notepad+",layout , siza = (500,500))
خب . اگه الان برنامه رو اجرا کنید ، نتیجهای که میخوایم رو تحویل نمیگیریم .
ما الان تعریف کردیم که یه پنجره باشه ، توی اینطوری باشه ، اونطوری باشه و اینا .
ولی براش اینکه نمایششون بده ، تعریف نشده .
توی tkinter برای اینکار از mainloop و pack استفاده میشد که تقریبا کار رو راحت میکرد . برای پایکیوت هم show بود .
اینجا باید تا یه جاهایی خودمون انجامش بدیم :)
اول از همه به مِتُدِ read برمیخوریم که تا حدی کار show و pack رو انجام میده :
window.read()
بعد باید یه while true بذاریم که تقریبا کار mainloop رو انجام بده .
while True :
window.read()
تقریبا تموم شد . آمّا ( یه سلامی هم بکنیم به همشری های عزیزم ! یاشاسین آذربایجان! ) ، برنامهمون بسته نمیشه! یعنی اگه اون ضربدری که معمولا بالای برنامه ها دیده میشه رو توی برنامهمون بزنیم ، برنامه ارور میده و خب ماهم از ارور خوشمون نمیاد .
چه کار کنیم ؟!
یه دوستی داشتیم ، به اسم window.read که این دوستمون دو تا مقدار برمیگردونه ، که ما یکیش رو میخوایم البته فعلا ولی خب دومی رو هم میگیریم که بعدا لازممون میشه .
حالا این دوتا چی هستن؟
یکیشون اتفاقاتی که توی برنامه توسط کاربر ایجاد شدهست و اونیکی هم در حال حاضر اون چیزی رو برمیگردونه که ما توی بخش قابل نوشتن برنامه نوشتیم .
ما فعلا هیچ کاری به دومی نداریم . بعدا میایم سراغش . الان فقط میخوایم رویداد ها رو زیر نظر داشته باشیم .
اسم اولی رو event و دومی رو value میذاریم .
با این حساب همچین چیزی خواهیم داشت :
while True :
event , value = window.read()
خب ، توی این متغیر میشه گفت که تمام رویداد ها و اتفاقات برنامه ذخیره میشه . مثلا فلان دکمه فشرده شد ، این منو انتخاب شد . ضربدر فشرده شد و ... .
توی اون متغیر دومی که باهاش کاری نداریم هم ، چیزایی مثلِ این کلمه توی اون باکس نوشته شد ، این متن اینجا نوشته شد ، فلان عدد وارد شد و... به صورت یه دیکشنری ذخیره میشن . که بعدا میرسیم بهش .
وقتی میخوایم برنامه رو ببندیم ، این درخواست ما توی event ذخیره میشه ، و اگر درخواست ما با اتریبیوتِ WIN_CLOSED برابر بود ، برنامهمون باید بسته بشه . توی tkinter و qt این دردسر وجود نداره ، اما اینجا چرا . باید خودمون بگیم چطور برنامه بسته بشه .
قاعدتا وقتی یه حلقه ی تکرار داره برنامه ی ما رو سرپا نگه میداره ، باید اول حلقه رو تموم کنیم ( بشکنیمش ) بعد به برنامه بگیم بسته بشه.
برای بستن برنامه از مِتُدِ close استفاده می کنیم ، و شکستن حلقه هم با یه if و break حل میشه .
نتیجه :
while True :
event , value = window.read()
if event == gui.WIN_CLOSED :
break
window.close()
اینم از این .
تا حالا چیزی که نوشتیم ، یه صفحهس که میشه توش نوشت و بعدم بستش . کارایی نداره ؛ ولی خب قدم اول هم بخشی از مسیره :)
مجموعا کدی که باید می نوشتیم هم اینه :
import PySimpleGUI as gui
# Define the GUI layout
layout = [
[gui.Multiline(font=('courier', 12), size=(80, 45))]
]
# Create the window
window = gui.Window('notepad+', layout , size=(800, 600))
while True :
event , values = window.read()
if event == gui.WIN_CLOSED :
break
window.close()
نکته : برنامه ی ما ، بدون این while True و break و if و close هم بالا میاد :) . دلیل در اصل ، ما زمانی از while True استفاده می کنیم که بخوایم به کار های کاربر واکنش نشون بدیم ، اونهم چند بار . یعنی برنامه بتونه دائم به درخواست کاربر جواب بده . با این حساب چون برنامه ی ما هنوز هیچ واکنش خاصی نشون نمیده به کاربر ، میشه بدون while هم نوشتش .
اما ما از الان while رو استفاده کردیم ، تا بعدا راحت تر باشیم.
با توجه به نکته ی قبل ، برنامه رو میشه اینطوری هم نوشت :
import PySimpleGUI as gui
# Define the GUI layout
layout = [
[gui.Multiline(font=('courier', 12), size=(80, 45))]
]
# Create the window
window = gui.Window('notepad+', layout , size=(800, 600))
window.read()
حالا با خیال راحت از کد اجرا بگیرید و نتیجه رو ببینید .
خداحافظیِ شیرین ، بعد از پر حرفی های من
خب! قسمت اول رو در همین لحظه به پایان میرسونیم
امیدوارم خوشتون اومده باشه . این قسمت هم یه مقداری طولانی شد ، چون داشتیم استارت می زدیم . از دفعات بعد کوتاه تر و پُر کُد تر خواهم نوشت :)
اگه نظر ، انتقاد یا پیشنهادی دارید خوشحال میشم برام بنویسید . و لطفا اگه خوشتون اومد این پست رو لایک کنید که بدجور به همایتتون احتیاج دارم .
راستی ، منتظر قسمت بعد هم حتما باشید .
روز و روزگارتون خُرَّم .