Posts: 46
Threads: 12
Joined: Jan 2021
Hello guys. I have a small problem with my app(It's not big ,just for experience).
As you can see in the first photo ,when I start my program ,all radiobuttons has a gray color inside(Its not selected),but it has no the default white color I want.When I select a choice,it's white(ok) .So,how can I fix this problem?
Also, as you can see in the 2nd photo when (for example) choose "orange juice" (a big word) and then I choose "Meat" (small word) ,the printing of the word is not obvious. How can I fix this problem?
1st photo
2nd photo
Code:
from tkinter import *
root = Tk()
root.title("Super Market")
root.geometry("1500x1300")
food = [
("Rice" , 0.99) , # value for radio_button -> 1
("Spaghetti" , 0.95) , # value for radio_button -> 2
("Ice cream" , 3.44) , # value for radio_button -> 3
("Pizza" , 7.50) , # value for radio_button -> 4
("Cheese" , 2.10) , # value for radio_button -> 5
("Cheddar" , 0.45) , # value for radio_button -> 6
("Cherry" , 0.88) , # value for radio_button -> 7
("Banana" , 0.40) , # value for radio_button -> 8
("Apple" , 0.67) , # value for radio_button -> 9
("Meat" , 7.28) , # value for radio_button -> 10
("Fish" , 9.72) , # value for radio_button -> 11
("Orange" , 0.62) , # value for radio_button -> 12
("Orange juice" , 2.10) , # value for radio_button -> 13
("Chocolate" , 0.99) , # value for radio_button -> 14
("Bread" , 0.55) # value for radio_button -> 15
]
food_name_var = StringVar()
frame = LabelFrame(root , relief = SUNKEN , bd = 1)
frame.grid(row = 0 , column = 0 , sticky = W)
r = 0
for food_name , food_price in food:
Radiobutton(frame , text = food_name , variable = food_name_var , value = r+1 , padx = 10 , pady = 5).grid(row = r , column = 0 , sticky = W)
label_price = LabelFrame(root , relief = SUNKEN , bd = 1 , text = "Price")
label_price.grid(row = r , column = 1 , sticky = W)
r += 1
def select_food(food_name):
label_print_food = Label(root , text = food_name)
label_print_food.grid(row = 0 , column = 4)
button = Button(root , text = "Basket" , command = lambda: select_food(food[ int(food_name_var.get() ) - 1][0]) )
button.grid(row = 0 , column = 3)
root.mainloop() Thanks in advance
Posts: 6,778
Threads: 20
Joined: Feb 2020
Feb-12-2021, 02:38 PM
(This post was last modified: Feb-12-2021, 02:38 PM by deanhystad.)
You need an IntVar(), not a StringVar(). You can use either IntVar() or StringVar(), but the variable type must match the value type.
This code uses a StringVar() and sets the RadioButton value to the food name. Since the button values are food names it makes more sens for food to be a dictionary with the name as the key.
root.geometry("1500x1300")
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}
frame = tk.LabelFrame(root, relief=tk.SUNKEN, bd=1)
frame.grid(row=0 ,column=0, sticky=tk.W)
food_var = tk.StringVar()
food_var.set(list(food)[0])
for r, name in enumerate(food):
tk.Radiobutton(frame , text=name, variable=food_var, value=name, padx=10, pady=5) \
.grid(row=r+1, column=0 , sticky=tk.W)
label_price = tk.LabelFrame(root, relief=tk.SUNKEN, bd=1, text="Price")
label_price.grid(row=r+1, column=1, sticky=tk.W)
def select_food(food_name):
tk.Label(grocery_list, text=food_name).pack(side=tk.TOP)
button = tk.Button(root, text="Basket", command=lambda: select_food(food_var.get()))
button.grid(row=0, column=3)
grocery_list = tk.Frame(root)
grocery_list.grid(row=0, column=4)
root.mainloop()
Posts: 377
Threads: 2
Joined: Jan 2021
I've modified your code so that select_food () re-configures label_print_food instead of recreating it each time. That takes care of the second problem. I inserted food_name_var.set ("Bread") after food_name_var = StringVar() and that should turn all of the buttons white like you wanted. Here's the altered code :
from tkinter import *
root = Tk()
root.title("Super Market")
root.geometry("1500x1300")
food = [
("Rice" , 0.99) , # value for radio_button -> 1
("Spaghetti" , 0.95) , # value for radio_button -> 2
("Ice cream" , 3.44) , # value for radio_button -> 3
("Pizza" , 7.50) , # value for radio_button -> 4
("Cheese" , 2.10) , # value for radio_button -> 5
("Cheddar" , 0.45) , # value for radio_button -> 6
("Cherry" , 0.88) , # value for radio_button -> 7
("Banana" , 0.40) , # value for radio_button -> 8
("Apple" , 0.67) , # value for radio_button -> 9
("Meat" , 7.28) , # value for radio_button -> 10
("Fish" , 9.72) , # value for radio_button -> 11
("Orange" , 0.62) , # value for radio_button -> 12
("Orange juice" , 2.10) , # value for radio_button -> 13
("Chocolate" , 0.99) , # value for radio_button -> 14
("Bread" , 0.55) # value for radio_button -> 15
]
food_name_var = StringVar()
food_name_var.set ("Bread")
frame = LabelFrame(root , relief = SUNKEN , bd = 1)
frame.grid(row = 0 , column = 0 , sticky = W)
r = 0
for food_name , food_price in food:
Radiobutton(frame , text = food_name , variable = food_name_var , value = r+1 , padx = 10 , pady = 5).grid(row = r , column = 0 , sticky = W)
label_price = LabelFrame(root , relief = SUNKEN , bd = 1 , text = "Price")
label_price.grid(row = r , column = 1 , sticky = W)
r += 1
def select_food(food_name):
label_print_food.configure (text = food_name)
button = Button(root , text = "Basket" , command = lambda: select_food(food[ int(food_name_var.get() ) - 1][0]) )
button.grid(row = 0 , column = 3)
label_print_food = Label(root , text = '')
label_print_food.grid(row = 0 , column = 4)
root.mainloop()
Posts: 46
Threads: 12
Joined: Jan 2021
Feb-12-2021, 05:03 PM
(This post was last modified: Feb-12-2021, 05:03 PM by Nick_tkinter.)
Hello again. I have some problems with my app. I want it to look something like this
Also ,I have a frame as you can see on the right side.So, when I click an item, I want to add it to the basket(Done),but the problem is that the item doesn't place down the previous one.( See here )
I also want to put "remove" buttons right from added items to remove items from list ,but this doesn't seem to work with my code below.
I put these "remove" buttons ,cause when user add an item many times, a counter increases ,so when he uses this button this counter discreses.
Code:
from tkinter import *
from PIL import Image , ImageTk
root = Tk()
root.title("Super Market")
root.geometry("1500x1300")
food = [
("Rice" , 0.99) , # value for radio_button -> 1
("Spaghetti" , 0.95) , # value for radio_button -> 2
("Ice cream" , 3.44) , # value for radio_button -> 3
("Pizza" , 7.50) , # value for radio_button -> 4
("Cheese" , 2.10) , # value for radio_button -> 5
("Cheddar" , 0.45) , # value for radio_button -> 6
("Cherry" , 0.88) , # value for radio_button -> 7
("Banana" , 0.40) , # value for radio_button -> 8
("Apple" , 0.67) , # value for radio_button -> 9
("Meat" , 7.28) , # value for radio_button -> 10
("Fish" , 9.72) , # value for radio_button -> 11
("Orange" , 0.62) , # value for radio_button -> 12
("Orange juice" , 2.10) , # value for radio_button -> 13
("Chocolate" , 0.99) , # value for radio_button -> 14
("Bread" , 0.55) , # value for radio_button -> 15
("Milk" , 1.00) # value for radio_button -> 16
]
NUMBER_OF_FOODS = 16
food_name_var = StringVar()
food_name_var.set(-200) # δεν δειχνει σε κανενα radio button αρχικα , αν εβαζα 1 θα εδειχνε στο 1ο προιον κοκ...
frame = LabelFrame(root , relief = SUNKEN , bd = 1)
frame.grid(row = 0 , column = 0 , sticky = W)
label_frame_food_info = LabelFrame(root , height = 600, width = 300 , relief = SUNKEN , bd = 2)
label_frame_food_info.place(x = 1200 , y = 50)
food_quantity = [0 for i in range(NUMBER_OF_FOODS)]
r = 0
y_lim_list = 0
for food_name , food_price in food:
Radiobutton(frame , text = food_name , variable = food_name_var , value = r+1 , padx = 10 , pady = 5).grid(row = r , column = 0 , sticky = W)
label_price = LabelFrame(root , relief = SUNKEN , bd = 1 , text = "Price")
label_price.grid(row = r , column = 1 , sticky = W)
r += 1
def select_food(food_name):
global y_lim_list
label_frame_food_info = LabelFrame(root , height = 600, width = 300 , relief = SUNKEN , bd = 2) # update shopping list
label_frame_food_info.place(x = 1200 , y = 50)
label_print_food = Label(label_frame_food_info , text = food_name + " (" + str(food_quantity[int(food_name_var.get() ) - 1] + 1) + ")")
food_quantity[int(food_name_var.get() ) - 1] += 1
if(food_quantity[int(food_name_var.get() ) - 1] >= 1):
button_remove_food = Button(label_frame_food_info , text = "Remove" , command = lambda: remove_selected_food(food[ int(food_name_var.get() ) - 1][0]))
button_remove_food.grid(row = y_lim_list , column = 1)
label_print_food.grid(row = y_lim_list , column = 0)
y_lim_list += 1
def remove_selected_food(item):
return
lock_logo = Image.open("shopping_basket.jpg")
lock_logo = lock_logo.resize( (60 , 60) , resample = 0)
lock_image = ImageTk.PhotoImage(lock_logo)
button = Button(root , image = lock_image , command = lambda: select_food(food[ int(food_name_var.get() ) - 1][0]))
button.grid(row = 0 , column = 3 , sticky = S)
label_info = Label(root , text = "Shopping basket")
label_info.place(x = 1294 , y = 20)
root.mainloop()
Posts: 6,778
Threads: 20
Joined: Feb 2020
Feb-12-2021, 08:21 PM
(This post was last modified: Feb-12-2021, 08:37 PM by deanhystad.)
A radio button group is not a good choice for this application. First you have to select an item, then you add it to the cart. Two clicks. Unless selecting an item brings up additional information to view before making a selection you should use a push button.
In the code below I make a button for each item in the inventory. Clicking the item adds it to the cart. The cart displays the item name and buttons to add more of the same, or to remove items.
There are likely widgets better than frame for displaying the cart, but this was easy and I am lazy.
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)
shopping_cart = {}
def update_cart():
print(shopping_cart)
for item in cart.winfo_children():
item.grid_forget()
item.destroy()
for r, item in enumerate(shopping_cart):
text = f'{shopping_cart[item]} x {item}'
tk.Label(cart, text=text, width=20) \
.grid(row=r, column=0)
tk.Button(cart, text=' + ', command=lambda n=item: add_item(n)) \
.grid(row=r, column=1)
tk.Button(cart, text=' - ', command=lambda n=item: remove_item(n)) \
.grid(row=r, column=2)
def add_item(item):
shopping_cart[item] = shopping_cart.get(item, 0) + 1
update_cart()
def remove_item(item):
if item in shopping_cart:
shopping_cart[item] -= 1
if shopping_cart[item] <= 0:
shopping_cart.pop(item)
update_cart()
for item in food:
button = tk.Button(inventory, text=item, width=20, command=lambda n=item: add_item(n))
button.pack(side=tk.TOP)
cart = tk.Frame(root)
cart.grid(row=0, column=1)
root.mainloop()
Posts: 46
Threads: 12
Joined: Jan 2021
(Feb-12-2021, 08:21 PM)deanhystad Wrote: A radio button group is not a good choice for this application. You could just use buttons.
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)
shopping_cart = {}
def update_cart():
print(shopping_cart)
for item in cart.winfo_children():
item.grid_forget()
item.destroy()
for r, item in enumerate(shopping_cart):
text = f'{shopping_cart[item]} x {item}'
tk.Label(cart, text=text, width=20) \
.grid(row=r, column=0)
tk.Button(cart, text=' + ', command=lambda n=item: add_item(n)) \
.grid(row=r, column=1)
tk.Button(cart, text=' - ', command=lambda n=item: remove_item(n)) \
.grid(row=r, column=2)
def add_item(item):
shopping_cart[item] = shopping_cart.get(item, 0) + 1
update_cart()
def remove_item(item):
if item in shopping_cart:
shopping_cart[item] -= 1
if shopping_cart[item] <= 0:
shopping_cart.pop(item)
update_cart()
for item in food:
button = tk.Button(inventory, text=item, width=20, command=lambda n=item: add_item(n))
button.pack(side=tk.TOP)
cart = tk.Frame(root)
cart.grid(row=0, column=1)
root.mainloop() Is there any way to do it with radio buttons,because I want to do it that way.Thanks
Posts: 6,778
Threads: 20
Joined: Feb 2020
Feb-12-2021, 08:44 PM
(This post was last modified: Feb-12-2021, 08:44 PM by deanhystad.)
I didn't say you couldn't do it that way, just that it is awkward. If you look at any GUI you like, you will see that radio buttons are use sparingly. If the number of choices grows above, say 5, a different widget is used.
Most applications with a large number of choices like this would use a list.
And don't use the replay button. It's not like we need a copy of my post for context.
Posts: 46
Threads: 12
Joined: Jan 2021
So,you tell me it's not a good idea to use radio buttons if I have many choices.Ok.I will remember this.Thanks.I will do it with buttons.
Posts: 46
Threads: 12
Joined: Jan 2021
My problem is how can I put a label and a button inside a frame.Do you know how can I do this?
Posts: 6,778
Threads: 20
Joined: Feb 2020
Feb-12-2021, 10:43 PM
(This post was last modified: Feb-12-2021, 10:43 PM by deanhystad.)
I provided an example. Didn't you try it?
|