8. Buttons, the table and starting the program¶
Lines 129–146
The last part puts everything together: seven buttons in a frame, the products table, the resize behaviour, the first fill of the table and, finally, the main loop that keeps the window open.
Code for this part¶
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()
Click a line number to jump to its explanation; click “line …” in an explanation to highlight that line in the code.
Line by line¶
- line 129
buttons = [('افزودن کالا', add), ('ویرایش کالا', edit), ('حذف کالا', delete),¶ - A list of (button label, function) pairs. The functions are written without parentheses, so the function objects themselves go into the list instead of being called.
- line 130
('ثبت فروش', sell), ('جستوجو', search), ('نمایش همه', refresh), ('گزارش فروش', report)]¶ - The rest of the same list; the open bracket on the previous line lets the list span two lines. The “show all” button is wired straight to
refresh, which shows every product when called with no arguments. - line 131
frame = ttk.Frame(root)¶ - Creates a
Frameinside the window so the buttons get a grid of their own. - line 132
frame.grid(row=4, column=0, columnspan=4, padx=10, pady=12)¶ - Places the frame on row 4 of the window, below the four form rows.
columnspan=4makes it span four columns. - line 133
for i, (label, action) in enumerate(buttons):¶ - Loops over the buttons;
iis the button's index (0 to 6). - line 134
ttk.Button(frame, text=label, command=lambda a=action: run(a)).grid(row=i // 4, column=i % 4, padx=4, pady=4)¶ - Creates a button and places it in the frame.
commandis the function called on a click.lambda a=action: run(a)builds a small anonymous function that callsrunwith this button's function.a=actioncaptures the current value right away; without it every button would run the loop's last value (report).i // 4gives the row andi % 4the column, so four buttons sit on the first row and three on the second. - line 137
table = ttk.Treeview(root, columns=columns, show='headings', height=13)¶ - Creates the table (
Treeview).show='headings'hides the default tree column (#0) so only our columns remain, andheight=13shows thirteen rows. - line 138
for key, label in [('name', 'نام کالا'), ('buy', 'قیمت خرید'), ('sell', 'قیمت فروش'), ('qty', 'موجودی')]:¶ - Loops over the column IDs and their header labels. The last column's header means “stock” rather than “quantity”.
- line 140
table.column(key, width=150, anchor='center')¶ - Makes the column 150 pixels wide with centred text.
- line 141
table.grid(row=5, column=0, columnspan=4, padx=10, pady=10, sticky='nsew')¶ - Places the table on row 5, across four columns.
sticky='nsew'sticks it to all four sides so it stretches with its cell. - line 142
table.bind('<<TreeviewSelect>>', choose)¶ - Binds the virtual event
<<TreeviewSelect>>tochoose: every time the table's selection changes,chooseruns. - line 143
root.grid_rowconfigure(5, weight=1)¶ - Gives row 5 (the table) a weight of 1, so extra height goes to it when the window grows.
Note
The order in which the whole file runs: class definition → create shop and the window → form → define the functions → buttons → table → refresh() → mainloop(). The functions on lines 77–127 do not run when they are defined; they run only when a button is clicked, or on line 145.
How it connects to the rest of the code¶
See also
buttons- Its functions are defined in part 6:
addline 93,editline 96,deleteline 99,sellline 102,searchline 105,reportline 109, plusrefreshon line 113. run- Defined on line 84.
table- Used in
refresh(line 114, line 115, line 118) andchoose(line 121, line 124). choose- Defined on line 120.
grid- The form takes rows 0 to 3 (line 72 and line 74), the buttons row 4 and the table row 5.
Check your understanding¶
Try to answer each question before opening it.
What goes wrong if line 134 uses
lambda: run(action)withouta=action?Show answer
The lambda reads
actionwhen it is clicked, not when it is created, so every button runs the loop's last value,report.Where does the button with index 5 appear?
Show answer
Row
5 // 4 = 1, column5 % 4 = 1: second row, second column. It is the “show all” button.Why must
root.mainloop()be the last line?Show answer
It blocks until the window is closed; code after it would only run after the program has finished.
What does
show='headings'hide on line 137?Show answer
The default tree column
#0, so only the four data columns are shown.