0

I have 3 labels and entry boxes, one is Sandwich, the other is drinks and the third one for showing their calculated costs.

There, I expect the user to enter the number of sandwiches and drinks they've had and calculate their price and show it in the third box by using this formula:

totalCost = (cod*30)+(cos*100)
costtotal.set(totalCost)

And it does so perfectly.

However, the problem is, that for example a user doesn't enter anything in the drinks field, I want the interpreter to interpret that empty field as 0 and calculate the sum. But, my program doesn't calculate it if any of the two fields (Drinks and Sandwiches) are empty. So, to counter this I tried:

if not drinks.get():
   yourVar = "0"
   cod=float(yourVar)

This is the error message I get:

File "C:/Users/Dell E6430/Desktop/trying.py", line 18, in Ref cod=float(drinks.get()) ValueError: could not convert string to float:

I don't get this error message when I input both fields.

However, it isn't working and the result is same. So, how do I solve that? Thanks.

Here's the full code:

from tkinter import*

root=Tk()
root.geometry("1600x800+0+0")

#------- convert to string
drinks=StringVar()
costtotal=StringVar()
sandwich=StringVar()

#----Frame
f1=Frame(root,width=800, height=700,relief=SUNKEN)
f1.pack(side=LEFT)


def Ref():
    cos=float(sandwich.get())
    cod=float(drinks.get())

    if not drinks.get():
        yourVar = "0"
        cod=float(yourVar)

    totalCost = (cod*30)+(cos*100)
    costtotal.set(totalCost)

lblSandwich=Label(f1,font=('arial',16,'bold'),text="Sandwich" , bd=16, anchor='w')
lblSandwich.grid(row=0,column=0)
txtSandwich=Entry(f1,font=('arial',16,'bold'),textvariable=sandwich,bd=10,insertwidth=4,bg="powder blue",justify='right')
txtSandwich.grid(row=0,column=1)


lblDrinks=Label(f1,font=('arial',16,'bold'),text="Drinks" , bd=16, anchor='w')
lblDrinks.grid(row=1,column=0)
txtDrinks=Entry(f1,font=('arial',16,'bold'),textvariable=drinks,bd=10,insertwidth=4,bg="powder blue",justify='right')
txtDrinks.grid(row=1,column=1)


lblcostTotal=Label(f1,font=('arial',16,'bold'),text="Cost of Drinks" , bd=16, anchor='w')
lblcostTotal.grid(row=2,column=0)
txtcostTotal=Entry(f1,font=('arial',16,'bold'),textvariable=costtotal,bd=10,insertwidth=4,bg="powder blue",justify='right')
txtcostTotal.grid(row=2,column=1)


btnTotal=Button(f1,padx=16,pady=8,bd=16,fg="black",font=('arial',16,'bold'),width=10,text="Total", bg="Powder Blue"\
,command=Ref).grid(row=7,column=1)

root.mainloop()

EDIT: By doing

cod=drinks.get()
if not drinks.get():
    yourVar = "0"
    cod=float(yourVar)
else:
    cod=float(drinks.get())

the program runs fine now.

Zain Abedin
  • 149
  • 9
  • Please don't confuse this to be the duplicate of this: https://stackoverflow.com/questions/15455113/tkinter-check-if-entry-box-is-empty As, in that link user just asks to check if the field is empty while I want the interpreter to interpret that empty field as having the value of 0. – Zain Abedin Oct 30 '19 at 13:59
  • You are getting an error message. Have you read the error message? – Bryan Oakley Oct 30 '19 at 14:00
  • @Bryan Oakley sorry for not adding it in the question earlier. This is the error message: File "C:/Users/Dell E6430/Desktop/trying.py", line 18, in Ref cod=float(drinks.get()) ValueError: could not convert string to float: I have updated it in the question – Zain Abedin Oct 30 '19 at 14:03
  • 2
    So what is that error telling you? It's telling you that you're trying to convert it to a float before you check for the value. – Bryan Oakley Oct 30 '19 at 14:04
  • No, that's for just getting the value from Entry. cod=float(drinks.get()) only gets the value. after that, I added if condition to check if the value we get is empty. – Zain Abedin Oct 30 '19 at 14:06
  • Did you mean that I do this? cod=drinks.get() if not drinks.get(): yourVar = "0" cod=float(yourVar) else: cod=float(drinks.get()) Because by doing this it's working fine now – Zain Abedin Oct 30 '19 at 14:23
  • Does this answer your question? [Tkinter check if entry box is empty](https://stackoverflow.com/questions/15455113/tkinter-check-if-entry-box-is-empty) – stovfl Oct 30 '19 at 14:32
  • 2
    look more closely at your code. `float(drinks.get())` does more than just get the value. Then read the error message again, it is literally telling you what the problem is. – Bryan Oakley Oct 30 '19 at 14:33
  • 1
    If `sandwich.get()` is anything other than a number it will error 100% of the time because you are wrapping `float()` around it. `fload()` can only work on a valid whole/decimal number. For example if the value of entry is an empty string it will error. – Mike - SMT Oct 30 '19 at 15:10
  • Yes, I didn't have that in mind that float will error in anything that isn't a number. It works now. Thanks for the help – Zain Abedin Oct 30 '19 at 19:23

1 Answers1

1

You cannot run float() over anything that is not a valid number. You should probably first check if your get() is returning a number with isnumeric() then if true run float if not set value to zero. That will handle anything not a number and even if it is a letter.

Note I have cleaned up your code a bit to more closely follow PEP8 standards as well as updated your import to help prevent overwriting. import tkinter as tk is always preferred over *.

Try this:

import tkinter as tk

root = tk.Tk()
root.geometry("1600x800+0+0")
cost_total = tk.StringVar()
sandwich = tk.StringVar()
drinks = tk.StringVar()

f1 = tk.Frame(root, width=800, height=700, relief='sunken')
f1.pack(side='left')


def ref():
    d = drinks.get()
    s = sandwich.get()
    if d.isnumeric():
        cod = float(d)
    else:
        cod = 0

    if s.isnumeric():
        cos = float(s)
    else:
        cos = 0

    total_cost = (cod * 30) + (cos * 100)
    cost_total.set(total_cost)


tk.Label(f1, font=('arial', 16, 'bold'), text="Sandwich", bd=16, anchor='w').grid(row=0, column=0)
tk.Entry(f1, font=('arial', 16, 'bold'), textvariable=sandwich, bd=10, insertwidth=4,
         bg="powder blue", justify='right').grid(row=0, column=1)

tk.Label(f1, font=('arial', 16, 'bold'), text="Drinks", bd=16, anchor='w').grid(row=1, column=0)
tk.Entry(f1, font=('arial', 16, 'bold'), textvariable=drinks, bd=10, insertwidth=4,
         bg="powder blue", justify='right').grid(row=1, column=1)

tk.Label(f1, font=('arial', 16, 'bold'), text="Cost of Drinks", bd=16, anchor='w').grid(row=2, column=0)
tk.Entry(f1, font=('arial', 16, 'bold'), textvariable=cost_total, bd=10, insertwidth=4,
         bg="powder blue", justify='right').grid(row=2, column=1)

tk.Button(f1, padx=16, pady=8, bd=16, fg="black", font=('arial', 16, 'bold'), width=10,
          text="Total", bg="Powder Blue", command=ref).grid(row=7, column=1)

root.mainloop()

Results:

enter image description here

To answer you question in the comments you can use a list or a couple list to manage large amounts of fields. Consider the below and let me know if you have any questions.

Code:

import tkinter as tk

list_of_foods = [['Coffie', 30], ['Tea', 20], ['Sandwich', 100], ['Apple', 50]]


def ref():
    total = 0
    for ndex, entry in enumerate(entry_list):
        value = entry.get()
        if value.isnumeric():
            total += float(value) * list_of_foods[ndex][1]
            print(total)
        else:
            total += 0
    double_var.set(total)


root = tk.Tk()
double_var = tk.DoubleVar(root, value=0)
entry_list = []

for ndex, sub_list in enumerate(list_of_foods):
    tk.Label(root, text=sub_list[0]).grid(row=ndex, column=0)
    entry_list.append(tk.Entry(root))
    entry_list[-1].grid(row=ndex, column=1)

tk.Entry(root, textvariable=double_var).grid(row=len(entry_list)+2, column=0, columnspan=2)
tk.Button(root, text='Total', command=ref).grid(row=len(entry_list)+3, column=0, columnspan=2)
root.mainloop()

Results:

enter image description here

Mike - SMT
  • 14,784
  • 4
  • 35
  • 79
  • Oh ok thanks. I had solved the problem but your way is much cleaner. Thanks – Zain Abedin Oct 30 '19 at 19:22
  • 1
    @ZainAbedin really the most important part is the number checking. So you do not have calculation issues. – Mike - SMT Oct 30 '19 at 19:29
  • yeah you're right. But, I have one question. Suppose, I have like 15-20 fields. Now, using if else and checking values for every field doesn't seem like a good idea. So, can we use it in function? I'm not sure how to do it. – Zain Abedin Oct 30 '19 at 19:41
  • 1
    @ZainAbedin sure. The best bet when you have many entry fields is to store the entry fields in a list and then work them by index. I will write up an example. – Mike - SMT Oct 30 '19 at 19:57
  • 1
    @ZainAbedin I added an example that will allow you to manage large amount of fields. You can do all the formatting yourself but the example should serve to illustrate how to get it done. – Mike - SMT Oct 30 '19 at 20:15