Bit of a pointless program (at the moment). It's intended more as practice for myself rather than anything else.
General idea is that you add details of a particular cat or dog, and it'll update a TreeView. A dog or cat can then be removed based on their assigned number.
Many thing I wasn't too sure on when creating this, such as best practices for creating a new form, accessing a class's parent attributes, and just general structure.
There's a lot more I want to add here (e.g. filters) - however I worry I'm repeating myself a lot throughout the code, and hardcoding things too much. The more functionality I try to add, the messier it seems to get.
import tkinter as tk
from tkinter import ttk
class App(tk.Frame):
def __init__(self, master = None):
self.master = master
self.my_storage = Storage()
# Setup Frames.
self.f1 = ttk.Frame(self.master)
self.f2 = ttk.Frame(self.master, padding = (10, 10, 10, 10))
self.f1.pack(fill = tk.X)
self.f2.pack(fill = tk.BOTH, expand = True)
# Setup GUI widgets.
self.widgets()
def widgets(self):
# Setup Tree widget to store animal objects.
self.tree = ttk.Treeview(self.f2)
headings = ["Type", "Name", "Breed", "Colour", "Size", "Bark", "Aggression", "Cuteness"]
self.tree["columns"] = (0, 1, 2, 3, 4, 5, 6, 7)
self.tree.column("#0", width = 45)
self.tree.heading("#0", text = "No.")
for index in range(len(headings)):
self.tree.column(index, width = 110)
self.tree.heading(index, text = headings[index])
# Setup Buttons and Entry widgets.
self.position = tk.IntVar()
self.add_dog = ttk.Button(self.f1, text = "Add Dog", command = lambda: self.add_window("Dog"))
self.add_cat = ttk.Button(self.f1, text = "Add Cat", command = lambda: self.add_window("Cat"))
self.remove_animal = ttk.Button(self.f1, text = "Remove by ID", command = self.remove_animal)
self.remove_animal_pos = ttk.Entry(self.f1, textvariable = self.position, width = 3)
# Add Widgets to GUI.
self.add_dog.pack(side = tk.LEFT)
self.add_cat.pack(side = tk.LEFT)
self.remove_animal.pack(side = tk.LEFT)
self.remove_animal_pos.pack(side = tk.LEFT)
self.tree.pack(expand = True, fill = tk.BOTH)
# Remove entry from library based on it's index / No
def remove_animal(self):
self.my_storage.remove_animal(self.position.get())
self.update_tree()
# Update the tree with the latest version of our storage list.
def update_tree(self):
self.tree.delete(*self.tree.get_children())
for i, x in enumerate(self.my_storage.storage):
obj_type = x.__class__.__name__
if obj_type == "Dog":
self.tree.insert("", "end", text = i, values = (obj_type, x.name, x.breed, x.colour, x.size, x.bark_sound, "n/a", "n/a"))
else:
self.tree.insert("", "end", text = i, values = (obj_type, x.name, x.breed, x.colour, x.size, "n/a", x.aggression, x.cuteness))
# Add a new window which allows us to input paramaters for our animal objects.
def add_window(self, type_of_animal):
self.window = tk.Toplevel(self.master)
AddAnimal(self.window, type_of_animal, self.my_storage, self.tree)
class AddAnimal(App):
def __init__(self, master, type_of_animal, my_storage, my_tree):
self.tree = my_tree
self.my_storage = my_storage
self.master = master
self.type_of_animal = type_of_animal
self.widgets()
def widgets(self):
# Set titles depending on type of animal we're adding.
if self.type_of_animal == "Dog":
self.titles = ["Name", "Breed", "Colour", "Size", "Bark Sound"]
else:
self.titles = ["Name", "Breed", "Colour", "Size", "Aggression", "Cuteness"]
# From titles, create the relevant entry boxes and labels.
self.entries = {}
for x in self.titles:
frame = tk.Frame(self.master)
frame.pack(side = "top", fill = "x")
label = tk.Label(frame, width = 20, text = x, anchor = 'w')
entry = tk.Entry(frame)
label.pack(side = "left")
entry.pack(side = "right", expand = True, fill = "x")
self.entries[x] = entry
self.add_bttn = tk.Button(self.master, text = "Add", command = lambda: self.add_to_tree(self.titles))
self.add_bttn.pack()
def add_to_tree(self, fields):
# Store all entry values in list.
lis = [self.entries[title].get() for title in self.titles]
# Depending on type of animal, create new animal object with relevant entry values.
if self.type_of_animal == "Dog":
name = lis[0]; breed = lis[1]; colour = lis[2]; size = lis[3]; bark_sound = lis[4];
obj = Dog(name, breed, colour, size, bark_sound)
else:
name = lis[0]; breed = lis[1]; colour = lis[2]; size = lis[3]; aggression = lis[4]; cuteness = lis[5]
obj = Cat(name, breed, colour, size, aggression, cuteness)
# Add object to our strorage list, update the tree with this list, and clos form.
self.my_storage.add_animal(obj)
self.update_tree()
self.master.destroy()
class Storage:
def __init__(self):
self.storage = []
def add_animal(self, animal):
self.storage.append(animal)
def remove_animal(self, position):
self.storage.pop(position)
class Animal:
def __init__(self, name, breed, colour, size):
self.name = name
self.breed = breed
self.colour = colour
self.size = size
class Dog(Animal):
def __init__(self, name, breed, colour, size, bark_sound):
super().__init__(name, breed, colour, size)
self.bark_sound = bark_sound
class Cat(Animal):
def __init__(self, name, breed, colour, size, aggression, cuteness):
super().__init__(name, breed, colour, size)
self.aggression = aggression
self.cuteness = cuteness
root = tk.Tk()
App(master = root)
root.mainloop()