I did these two different sets of code that does the same function on tkinter. The simplediaglog version works just fine but I wanted to use entry (because I want to display the output on the same pop-up window), which does not work.
The problem lies mainly in multiplying a list of float values in a dictionary to the entry input value and getting python to even recognise the entry input as int.
I tried restructuring the try-except-else, tried using different ways to convert the entry input to integer using IntVar(). I also tried indexing the dictionary i.e. x[y][0]. I tried putting the float values into string e.g. x = {"A": "2.3", "B": "0.3"}. But nothing works, keep getting different errors but all boils down to one thing: unable to multiply integer/str with float values from dictionary.
def p(y):
while True:
Q = simpledialog.askstring("test", "Enter number:")
try:
Q = int(Q)
if Q is None:
break
elif Q <=0 or Q> 10:
raise ValueError
else:
W = str(round(Q * x[y], 1)) # Round off to 1 d.p
messagebox.showinfo("test", "Ans is\n" + W + " minute(s)")
break
except:
messagebox.showerror("Error", "enter a value from 0 to 10")
break
This code works and showed everything correctly.
BTW, for below code, the place geometry is something I put randomly to see if overall code works, I don't think the error is due to the geometry.
The above simpledialog code works.
However, this entry widget code does not:
def p(y):
root = Tk()
root.title("Average Waiting Time")
root.geometry("800x500")
Label(root, text="Enter number of people: ").place(x=20, y=30)
Q = Entry(root, bd =5)
Q.place(x=220, y=30)
def B():
Q_input = Q.get()
while True:
try:
int(Q_input)
if Q_input is None:
continue
elif Q_input <=0 or Q_input > 10:
raise ValueError
else:
W = str(round(Q_input * x[y], 1)) # Round off to 1 d.p
Label(root, "Ans\n" + W + " minute(s)").place(x=50, y=500)
except:
messagebox.showerror("Error", "enter a value from 0 to 10")
break
ok = Button (root, text="OK", command = B)
ok.place(x=300, y=300)
cancel = Button (root, text="Cancel", command = root.destroy)
cancel.place(x=400,y=300)
root.mainloop()
This is my dictionary for the list of float values:
x = {"A": 0.8, "B": 2.5, "C": 1.2}
I expect to see a label with something like Ans 2.3 minute(s) appearing in the same window as the entry widget.
But even if I key in an int such as '5' into the entry input, the try-except does not convert it to int because I keep getting the "Error" message: "enter a value from 0 to 10".
Why is this so? Is it because it is an entry widget and not simpledialog because it worked for simplediaglog?
Also, even when I got to the line for W (manage to convert Q_input) to integer, it shows error: 'str' object has no attribute 'items'.
My main question is why the float dictionary list (and type conversion from str to int) is able to register with simpledialog but not for entry widget? What is the difference? Is it possible to multiply float values from dictionary with an integer from entry input?
Also, are there any other methods to display the output on the same pop-up window besides entry widget?
Thank you in advance!
Edit: So, I tried converting Q_input to int before while loop and printing it. If I key in '5', it prints '5'. I know it did convert to int because when I input 'hi', there is an error: invalid literal for int() with base 10: 'hi'.
I changed int(Q_input)
to Q_input=int(Q_input)
too. Per suggestion, I also changed continue
to break
under if Q_input is None:
.
But, the try-except still does not work, it did not even try converting Q_input to int, it simply skipped straight to except
.
Sorry for asking so many questions, so I will just sum it up into one question:
Is my try-except
code not working because of differences between simpledialog and entry widget, if so what is the reason and if not why is the code not working then?
Solution:
I realised something , all along I had not been able to display the label because of this: Label(root, "Ans\n" + W + " minute(s)").place(x=50, y=500)
. I did not put text=
, haha I was able to show the label successfully after adding text=
. My bad, so all along the problem was not converting the entry input to integer. There is a need to change int(Q_input)
to Q_input=int(Q_input)
though. I just sort of jump to the conclusion that the error was because of type conversion because the programme kept going straight to except
.
I often use a function to safely convert a string to an int or a float, e.g. to_int
below.
The code below creates an answer Label that's used as required. The original code created a label for every click of the button.
from tkinter import *
def to_int(string, fail = 0):
try:
return int(string)
except ValueError:
return fail
x = {"A": 0.8, "B": 2.5, "C": 1.2}
def p(y):
root = Tk()
root.title("Average Waiting Time")
root.geometry("800x500")
Label(root, text="Enter number of people: ").place(x=20, y=30)
Q = Entry(root, bd =5)
Q.place(x=220, y=30)
answer = StringVar()
answer.set("")
Label(root, textvariable = answer ).place(x=50, y=500)
def B():
Q_input = Q.get()
v = to_int(Q_input, -1)
# Returning <0 triggers the error message
if v <=0 or v > 10:
answer.set("Enter a value from 0 to 10")
else:
W = str(round(v * x[y], 1)) # Round off to 1 d.p
answer.set("Ans\n" + W + " minute(s)")
print(answer.get())
ok = Button (root, text="OK", command = B)
ok.place(x=300, y=300)
cancel = Button (root, text="Cancel", command = root.destroy)
cancel.place(x=400,y=300)
root.mainloop()