Posts: 43
Threads: 18
Joined: Jun 2020
The following code was primarily written by Yoriz. I'm using this code to better understand classes.
In three of the classes tk.Frame is shown in parentheses. 'At first I thought this was inheritance but tk.Frame is not the name of a parent class. Why is tk.Frame in parentheses?
import tkinter as tk
class Main:
def __init__(self, root):
self.root = root
self.root.geometry("800x800")
self.create_start_frame()
def create_start_frame(self):
self.start_frame = StartFrame(self.root)
self.start_frame.btn_start.bind(
'<Button-1>', self.on_start_frame_btn_start)
self.start_frame.pack()
def on_start_frame_btn_start(self, event):
self.start_frame.destroy()
self.second_menu_frame = SecondMenuFrame(root)
self.second_menu_frame.btn_option1.bind(
'<Button-1>', self.on_second_menu_frame_btn_option1)
self.second_menu_frame.pack()
def on_second_menu_frame_btn_option1(self, event):
self.second_menu_frame.destroy()
self.final_frame = FinalFrame(root)
self.final_frame.pack()
class StartFrame(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
tk.Label(self, text='StartFrame').pack()
self.btn_start = tk.Button(
self, text="Press here to start", bg="red", fg="black", font="Helvitica 30")
self.btn_start.pack()
class SecondMenuFrame(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
tk.Label(self, text='SecondMenuFrame').pack()
self.btn_option1 = tk.Button(self, text="Option1", bg="white",
fg="firebrick", relief="groove", font="Helvitica 30")
self.btn_option1.pack()
class FinalFrame(tk.Frame):
def __init__(self, parent):
super().__init__(parent)
tk.Label(self, text='FinalFrame').pack()
self.btn_final1 = tk.Button(self, text="finalsel1", bg="white",
fg="firebrick", relief="groove", font="Helvitica 30", )
self.btn_final1.pack()
if __name__ == "__main__":
root = tk.Tk()
main = Main(root)
root.mainloop()
Posts: 1,144
Threads: 114
Joined: Sep 2019
If I'm not mistaken tk.Frame is a class in tkinter
Posts: 12,025
Threads: 484
Joined: Sep 2016
Feb-12-2021, 03:01 AM
(This post was last modified: Feb-12-2021, 03:02 AM by Larz60+.)
If you ever want to know the type of ab object try:
>>> import tkinter as tk
>>> type(tk.Frame)
<class 'type'>
>>> class whadayacallit(tk.Frame) inherits class tk method Frame
Posts: 6,779
Threads: 20
Joined: Feb 2020
What made you think that Frame is not a class? This post, and the post about not making an instance lead me to think you are confused about classes and objects and variables.
Posts: 43
Threads: 18
Joined: Jun 2020
(Feb-12-2021, 02:54 PM)deanhystad Wrote: What made you think that Frame is not a class? This post, and the post about not making an instance lead me to think you are confused about classes and objects and variables.
Deanhystad,
You are right. I am confused about classes. Most of the videos I have watched lead to creating an object(instance) such as a student and storing his/her name, address, GPA, school etc in this student object. Using classes with Tkinter seems very different to me.
I am able to create several menus using 1 class and several class methods. But I thought it would be better programming to use multiple classes. If I use a Tkinter course they usually don't use classes.
If you know of any tkinter books or videos that use classes, please let me know.
Posts: 6,779
Threads: 20
Joined: Feb 2020
Feb-13-2021, 04:32 AM
(This post was last modified: Feb-13-2021, 04:32 AM by deanhystad.)
Use classes when they make sense. An object should have an identity. You should be able to describe not only what it does, but what it is in a few short sentences. Just today I answered a question about a shopping application that used a list of buttons and labels to represent a shopping cart. I am lazy, so I will rework that example to use a class for the shopping cart.
import tkinter as tk
root = tk.Tk()
root.title("Super Market")
food = {
"Rice": 0.99,
"Spaghetti": 0.95,
"Ice cream": 3.44,
"Pizza": 7.50,
"Cheese": 2.10,
"Cheddar": 0.45,
"Cherry": 0.88,
"Banana": 0.40,
"Apple": 0.67,
"Meat": 7.28,
"Fish": 9.72,
"Orange": 0.62,
"Orange juice": 2.10,
"Chocolate": 0.99,
"Bread": 0.55}
inventory = tk.Frame(root)
inventory.grid(row=0, column=0)
class ShoppingCart(tk.Frame):
"""I am a list of labels and buttons that represents a shopping
cart. Items are kept in a dictionary. Each item associated with
an item count. When drawn, I create a label, an add button and
a subtract button for each item in items. Pressing the add button
increases the item count. Pressing the subtract button decreases
the item count. If the item count goes to zero, the item is
removed from the eictionary.
"""
def __init__(self, *args, **kvargs):
super().__init__(*args, **kvargs)
self.items = {}
def append(self, item):
"""Add item to cart"""
self.items[item] = self.items.get(item, 0) + 1
self.update()
def remove(self, item):
"""Remove item from cart"""
if item in self.items:
self.items[item] -= 1
if self.items[item] <= 0:
self.items.pop(item)
self.update()
def update(self):
"""Update items display"""
# Remove all items from display
for item in self.winfo_children():
item.grid_forget()
item.destroy()
# For each item create a label, an add button and a
# remove button.
for r, item in enumerate(self.items):
text = f'{self.items[item]} x {item}'
tk.Label(cart, text=text, width=20) \
.grid(row=r, column=0)
tk.Button(cart, text=' + ', command=lambda n=item: self.append(n)) \
.grid(row=r, column=1)
tk.Button(cart, text=' - ', command=lambda n=item: self.remove(n)) \
.grid(row=r, column=2)
cart = ShoppingCart(root)
cart.grid(row=0, column=1)
for item in food:
button = tk.Button(inventory, text=item, width=20, \
command=lambda n=item: cart.append(n))
button.pack(side=tk.TOP)
root.mainloop() If I weren't so lazy I would probably make the class an iterator so I could do something like this:
total = 0
for item, count in cart.items():
price = food[item]
subtotal = count * price
total += subtotal
print(f'{count:3} {item} @ {price:5.2} = {subtotal:5.2} ShoppingCart makes a decent class because it is a thing that you can describe. It is a shopping cart. It holds things you want to purchase. You can put things in the cart and take things out of the cart. The interface provides buttons to make this easy.
I have never written code that uses a student object or a employee object. Most of my classes represent something slightly more abstract.
Posts: 43
Threads: 18
Joined: Jun 2020
(Feb-13-2021, 04:32 AM)deanhystad Wrote: Use classes when they make sense. An object should have an identity. You should be able to describe not only what it does, but what it is in a few short sentences. Just today I answered a question about a shopping application that used a list of buttons and labels to represent a shopping cart. I am lazy, so I will rework that example to use a class for the shopping cart.
import tkinter as tk
root = tk.Tk()
root.title("Super Market")
food = {
"Rice": 0.99,
"Spaghetti": 0.95,
"Ice cream": 3.44,
"Pizza": 7.50,
"Cheese": 2.10,
"Cheddar": 0.45,
"Cherry": 0.88,
"Banana": 0.40,
"Apple": 0.67,
"Meat": 7.28,
"Fish": 9.72,
"Orange": 0.62,
"Orange juice": 2.10,
"Chocolate": 0.99,
"Bread": 0.55}
inventory = tk.Frame(root)
inventory.grid(row=0, column=0)
class ShoppingCart(tk.Frame):
"""I am a list of labels and buttons that represents a shopping
cart. Items are kept in a dictionary. Each item associated with
an item count. When drawn, I create a label, an add button and
a subtract button for each item in items. Pressing the add button
increases the item count. Pressing the subtract button decreases
the item count. If the item count goes to zero, the item is
removed from the eictionary.
"""
def __init__(self, *args, **kvargs):
super().__init__(*args, **kvargs)
self.items = {}
def append(self, item):
"""Add item to cart"""
self.items[item] = self.items.get(item, 0) + 1
self.update()
def remove(self, item):
"""Remove item from cart"""
if item in self.items:
self.items[item] -= 1
if self.items[item] <= 0:
self.items.pop(item)
self.update()
def update(self):
"""Update items display"""
# Remove all items from display
for item in self.winfo_children():
item.grid_forget()
item.destroy()
# For each item create a label, an add button and a
# remove button.
for r, item in enumerate(self.items):
text = f'{self.items[item]} x {item}'
tk.Label(cart, text=text, width=20) \
.grid(row=r, column=0)
tk.Button(cart, text=' + ', command=lambda n=item: self.append(n)) \
.grid(row=r, column=1)
tk.Button(cart, text=' - ', command=lambda n=item: self.remove(n)) \
.grid(row=r, column=2)
cart = ShoppingCart(root)
cart.grid(row=0, column=1)
for item in food:
button = tk.Button(inventory, text=item, width=20, \
command=lambda n=item: cart.append(n))
button.pack(side=tk.TOP)
root.mainloop() If I weren't so lazy I would probably make the class an iterator so I could do something like this:
total = 0
for item, count in cart.items():
price = food[item]
subtotal = count * price
total += subtotal
print(f'{count:3} {item} @ {price:5.2} = {subtotal:5.2} ShoppingCart makes a decent class because it is a thing that you can describe. It is a shopping cart. It holds things you want to purchase. You can put things in the cart and take things out of the cart. The interface provides buttons to make this easy.
I have never written code that uses a student object or a employee object. Most of my classes represent something slightly more abstract.
Thanks deanhystad for shopping cart. I will be studying it to see how it works.
|