۸. دکمهها، جدول و اجرای برنامه¶
خط ۱۲۹ تا ۱۴۶
بخش آخر همهچیز را کنار هم میگذارد: هفت دکمه در یک قاب، جدول کالاها، تنظیم کشیده شدن پنجره، پر کردن اولیهی جدول و در پایان حلقهی اصلی که پنجره را باز نگه میدارد.
کد این بخش¶
129buttons = [('افزودن کالا', add), ('ویرایش کالا', edit), ('حذف کالا', delete),130 ('ثبت فروش', sell), ('جستوجو', search), ('نمایش همه', refresh), ('گزارش فروش', report)]131frame = ttk.Frame(root)132frame.grid(row=4, column=0, columnspan=4, padx=10, pady=12)133for i, (label, action) in enumerate(buttons):134 ttk.Button(frame, text=label, command=lambda a=action: run(a)).grid(row=i // 4, column=i % 4, padx=4, pady=4)135 136columns = ('name', 'buy', 'sell', 'qty')137table = ttk.Treeview(root, columns=columns, show='headings', height=13)138for key, label in [('name', 'نام کالا'), ('buy', 'قیمت خرید'), ('sell', 'قیمت فروش'), ('qty', 'موجودی')]:139 table.heading(key, text=label)140 table.column(key, width=150, anchor='center')141table.grid(row=5, column=0, columnspan=4, padx=10, pady=10, sticky='nsew')142table.bind('<<TreeviewSelect>>', choose)143root.grid_rowconfigure(5, weight=1)144root.grid_columnconfigure(3, weight=1)145refresh()146root.mainloop()
روی شمارهی هر خط بزن تا به توضیحش بروی؛ روی «خط …» در توضیح بزن تا همان خط در کد روشن شود.
توضیح خط به خط¶
- خط ۱۲۹
buttons = [('افزودن کالا', add), ('ویرایش کالا', edit), ('حذف کالا', delete),¶ - لیستی از جفتهای (متن دکمه، تابع). توابع بدون پرانتز نوشته شدهاند، یعنی خود تابع در لیست میرود و اجرا نمیشود.
- خط ۱۳۰
('ثبت فروش', sell), ('جستوجو', search), ('نمایش همه', refresh), ('گزارش فروش', report)]¶ - ادامهی همان لیست. پرانتز باز در خط قبل اجازه میدهد لیست در دو خط نوشته شود. «نمایش همه» مستقیم به
refreshوصل است که بدون ورودی همهی کالاها را نشان میدهد. - خط ۱۳۱
frame = ttk.Frame(root)¶ - یک قاب (
Frame) داخل پنجره میسازد تا دکمهها شبکهی جدای خودشان را داشته باشند. - خط ۱۳۲
frame.grid(row=4, column=0, columnspan=4, padx=10, pady=12)¶ - قاب را در ردیف ۴ پنجره (زیر چهار ردیف فرم) میگذارد.
columnspan=4یعنی چهار ستون را پوشش میدهد. - خط ۱۳۴
ttk.Button(frame, text=label, command=lambda a=action: run(a)).grid(row=i // 4, column=i % 4, padx=4, pady=4)¶ - دکمه را میسازد و در قاب میگذارد.
commandتابعی است که با کلیک اجرا میشود.lambda a=action: run(a)یک تابع بینام میسازد کهrunرا با تابع همین دکمه صدا میزند.a=actionمقدار فعلی را همان لحظه نگه میدارد؛ بدون آن، همهی دکمهها آخرین مقدار حلقه (report) را اجرا میکردند.i // 4ردیف وi % 4ستون را میدهد، پس چهار دکمه در ردیف اول و سه دکمه در ردیف دوم قرار میگیرند. - خط ۱۳۷
table = ttk.Treeview(root, columns=columns, show='headings', height=13)¶ - جدول (
Treeview) را میسازد.show='headings'ستون درختی پیشفرض (#0) را پنهان میکند و فقط ستونهای ما میمانند.height=13یعنی ۱۳ ردیف در دید است. - خط ۱۳۸
for key, label in [('name', 'نام کالا'), ('buy', 'قیمت خرید'), ('sell', 'قیمت فروش'), ('qty', 'موجودی')]:¶ - حلقه روی شناسهی ستون و عنوان فارسی آن. اینجا عنوان ستون آخر «موجودی» است، نه «تعداد».
- خط ۱۴۱
table.grid(row=5, column=0, columnspan=4, padx=10, pady=10, sticky='nsew')¶ - جدول را در ردیف ۵ و به پهنای چهار ستون میگذارد.
sticky='nsew'یعنی به هر چهار جهت بچسبد و با بزرگ شدن خانه کشیده شود. - خط ۱۴۲
table.bind('<<TreeviewSelect>>', choose)¶ - رویداد مجازی
<<TreeviewSelect>>را بهchooseوصل میکند. هر بار انتخاب جدول عوض شود،chooseاجرا میشود. - خط ۱۴۳
root.grid_rowconfigure(5, weight=1)¶ - به ردیف ۵ (جدول) وزن ۱ میدهد: وقتی پنجره بلندتر شود، فضای اضافه به این ردیف میرسد.
یادداشت
ترتیب اجرای کل فایل: تعریف کلاس ← ساخت shop و پنجره ← فرم ← تعریف توابع ← دکمهها ← جدول ← refresh() ← mainloop(). توابع خط ۷۷ تا ۱۲۷ در زمان تعریف اجرا نمیشوند؛ فقط با کلیک دکمهها یا در خط ۱۴۵ اجرا میشوند.
ارتباط با بقیهی کد¶
همچنین ببینید
buttons- توابع آن در بخش ۶ تعریف شدهاند:
addخط ۹۳،editخط ۹۶،deleteخط ۹۹،sellخط ۱۰۲،searchخط ۱۰۵،reportخط ۱۰۹، وrefreshدر خط ۱۱۳. run- در خط ۸۴ تعریف شده است.
table- در
refresh(خط ۱۱۴، خط ۱۱۵، خط ۱۱۸) وchoose(خط ۱۲۱، خط ۱۲۴) استفاده میشود. choose- در خط ۱۲۰ تعریف شده است.
grid- فرم ردیفهای ۰ تا ۳ را گرفته (خط ۷۲ و خط ۷۴)، دکمهها ردیف ۴ و جدول ردیف ۵.
سؤالهای تمرینی¶
اول خودت جواب بده، بعد جواب را باز کن.
اگر در خط ۱۳۴ بهجای
a=actionفقطlambda: run(action)نوشته شود چه میشود؟نمایش جواب
لامبدا مقدار
actionرا هنگام کلیک میخواند، نه هنگام ساخت؛ پس همهی دکمهها آخرین مقدار حلقه یعنیreportرا اجرا میکنند.دکمهای که شمارهاش ۵ است کجا قرار میگیرد؟
نمایش جواب
ردیف
5 // 4 = 1و ستون5 % 4 = 1: ردیف دوم، ستون دوم. همان دکمهی «نمایش همه» است.چرا
root.mainloop()باید آخرین خط باشد؟نمایش جواب
این خط تا بسته شدن پنجره منتظر میماند؛ کد بعد از آن فقط بعد از تمام شدن برنامه اجرا میشد.
show='headings'در خط ۱۳۷ چه چیزی را پنهان میکند؟نمایش جواب
ستون درختی پیشفرض
#0، تا فقط چهار ستون داده دیده شوند.