I'm in the process of making my first GUI with Python. I'm trying to make something for work, so I've replaced all the info with fruits. It just lets the user tick some boxes, then creates a word doc
It's quite messy, and the variable names will be renamed later. But what I wanted to ask about was the functions I've defined. I wasn't sure whether to define the ship_collect and ship_click function within the FruitClass class, or outside of it.
I figured it made more sense to put it outside, that way the function only gets defined once. Whereas if I defined it inside in the class, it would be defined every time an instance gets created, taking up more memory - is this correct or am I totally wrong here?
Additionally, I thought the functions would have to be defined before the class, since some the widgets defined in the class use them for commands...
If the functions are defined outside the class, would it make more sense to create the widgets (for example .ent_qty) within the functions, or within the class? Again I thought outside made more sense, as it seemed more sensible to define these widgets only if the original checkbox gets ticked.
import tkinter as tk
from tkinter import ttk
from docx import Document
def ship_collect(fruit_object):
'''Function to make additional checkbuttons appear if the first column boxes get ticked.'''
if fruit_object.chkVal.get() == True:
# quantity
fruit_object.lbl_qty = tk.Label(master=fruit_object.frm, text="Quantity: ", bg="red")
fruit_object.ent_qty = tk.Entry(master=fruit_object.frm, width=10, bg="blue")
fruit_object.lbl_qty.grid(row=1, column=0, sticky='e')
fruit_object.ent_qty.grid(row=1, column=1, sticky='w', padx=(0,20))
# shipping/collect
fruit_object.chkVal_ship = tk.BooleanVar()
fruit_object.chkVal_ship.set(False)
fruit_object.chk_ship = tk.Checkbutton(master=fruit_object.frm, text="ship", variable=fruit_object.chkVal_ship, bg="green", command=lambda fruit_object=fruit_object:ship_clicked(fruit_object))
fruit_object.chk_ship.grid(row=0,column=2, sticky='w')
fruit_object.chkVal_collect = tk.BooleanVar()
fruit_object.chkVal_collect.set(False)
fruit_object.chk_collect = tk.Checkbutton(master=fruit_object.frm, text="collect", variable=fruit_object.chkVal_collect, bg="yellow")
fruit_object.chk_collect.grid(row=1,column=2, sticky='w')
else:
fruit_object.chk_ship.grid_forget()
fruit_object.chk_collect.grid_forget()
fruit_object.lbl_qty.grid_forget()
fruit_object.ent_qty.grid_forget()
fruit_object.combo_ship.grid_forget()
def ship_clicked(fruit_object):
''' Create drop-down menus if ship button gets clicked'''
if fruit_object.chkVal_ship.get() == True:
fruit_object.combo_ship = ttk.Combobox(master=fruit_object.frm,
values=[
"Next day - £5",
"Standard - £2"],
state="readonly")
fruit_object.combo_ship.grid(row=0, column=3)
fruit_object.combo_ship.current(0)
class FruitClass:
def __init__(self, fruitname):
self.fruitname = fruitname
self.chkVal = tk.BooleanVar()
self.chkVal.set(False)
self.frm = tk.Frame(master=frm_fruits)
self.chk = tk.Checkbutton(master=self.frm, text=self.fruitname, variable=self.chkVal, command = lambda self=self: ship_collect(self))
self.chk.grid(row=0,column=0, sticky='w')
self.frm.columnconfigure(0, weight=1, minsize=80)
window = tk.Tk()
lbl_fruits = tk.Label(master=window, text="Select fruits:")
lbl_fruits.grid(row=0, sticky="w")
frm_fruits = tk.Frame(master=window)
frm_fruits.grid(row=1, column=0)
# use a list of fruit names to create a dict of objects
objectNames = ('apple','banana','orange','pear','mango')
objectDictionary = {}
for name in objectNames:
objectDictionary[name] = FruitClass(fruitname=name)
# append each fruit frame (containing checkboxes) to the window
for i, k in enumerate(objectDictionary):
objectDictionary[k].frm.grid(row=i, column=0, sticky='w', pady=(0,10))
def onSubmit():
myDoc = Document()
myTable = myDoc.add_table(1,3)
heading_cells = myTable.rows[0].cells
heading_cells[0].text = 'Fruit'
heading_cells[1].text = 'Quantity'
heading_cells[2].text = 'Delivery'
# check which boxes were ticked, add these to the table in word
for name, obj in objectDictionary.items():
if obj.chkVal.get() == True:
cells = myTable.add_row().cells
cells[0].text = name
cells[1].text = str(obj.ent_qty.get())
if obj.chkVal_ship.get() == True:
cells[2].text = obj.combo_ship.get()
myTable.style = 'LightShading-Accent1'
myDoc.save('shopping.docx')
btn_submit = tk.Button(
master=window,
text="Submit",
command=onSubmit
)
btn_submit.grid(row=3, column=3)
window.mainloop()