Python Forum
Python3 tkinter radiobutton problem
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Python3 tkinter radiobutton problem
#1
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 Smile
Reply
#2
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()
Reply
#3
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()
Reply
#4
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()
Reply
#5
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()
Reply
#6
(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
Reply
#7
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.
Reply
#8
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. Smile
Reply
#9
My problem is how can I put a label and a button inside a frame.Do you know how can I do this?
Reply
#10
I provided an example. Didn't you try it?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to dynamically change radiobutton text kenwatts275 2 331 Mar-05-2021, 02:25 AM
Last Post: deanhystad
  tkinter python button position problem Nick_tkinter 3 513 Jan-31-2021, 05:15 AM
Last Post: deanhystad
  [Tkinter] RadioButton Maryan 2 325 Oct-23-2020, 09:36 PM
Last Post: Maryan
  Call local variable of previous function from another function with Python3 & tkinter Hannibal 5 567 Oct-12-2020, 09:16 PM
Last Post: deanhystad
  [Tkinter] ClockIn/Out tkinter problem Maryan 2 399 Oct-12-2020, 03:42 AM
Last Post: joe_momma
  tkinter| listbox.insert problem Maryan 3 447 Sep-29-2020, 05:34 PM
Last Post: Yoriz
  Tkinter problem DPaul 6 912 May-28-2020, 03:40 PM
Last Post: DPaul
  [Tkinter] Tkinter wouldn't work with python3.8.3 shay_xs 2 937 May-24-2020, 11:48 PM
Last Post: Larz60+
  [Tkinter] How to create radiobutton in numpy gui python? luthfidali 2 792 May-23-2020, 10:35 AM
Last Post: timo
  [Tkinter] Tkinter - I have problem after import varaible or function from aGUI to script johnjh 2 695 Apr-17-2020, 08:12 PM
Last Post: johnjh

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020