So basically, I am trying to create a python program to detect whether the 3 digit number entered by the user is an Armstrong number or not. It's working fine in python, except it's printing the answer 3 times in terminal. But when I use tkinter, I get some problems since I basically just got to know by it just a few hours ago and don't really know how to use it. The problem I get is in > operator, I'm receiving data in Entry() but > operator is for integers so it is giving me type errors.
Here's the error
TypeError: '>' not supported between instances of 'int' and 'Entry'
Here is my code
import re
from tkinter import *
root = Tk()
label = Label(root, text="Enter a 3 digit Number")
label.pack()
num = Entry(root, width=50, bg="orangered")
num.pack()
def myclick():
Sum = 0
temp = num
if 1000 > num > 99:
while temp > 0:
digit = temp % 10
Sum += digit ** 3
temp //= 10
if num == Sum:
label2 = Label(root, num, "is an Armstrong number")
label2.pack()
else:
label3 = Label(root, num, "is not an Armstrong number")
label3.pack()
else:
label4 = Label(root,
"The number you entered is not a 3 digit number, Please Enter a number between 100 and 999")
label4.pack()
MyButton = Button(root, text="Click", command=myclick)
MyButton.pack()
root.mainloop()
All I want is to make this program work in a gui, and stop printing the result thrice. Can anyone help me?
As num is an Entry widget, you cannot use it directly in value comparison. Use int(num.get()) to convert the content to an integer number. You also need to cater invalid input, for example something like "abc", using try / except.
Also you create new label (for showing the result) in each iteration of the while loop, that is why you get 3 labels for each checking. It is better to create the result label once outside myclick() and update it inside the function instead.
Below is the modified myclick():
def myclick():
try:
number = num.get()
value = int(number)
if 999 >= value >= 100:
total = sum(int(digit)**3 for digit in number)
message = f"{value} {'is' if value == total else 'is not'} an Armstrong number"
else:
message = "Enter a number between 100 and 999"
except ValueError:
message = f"'{number}' is not a valid number"
result.config(text=message) # show the result
And create result label outside the function:
result = Label(root)
result.pack()
Related
Here I've uploaded the entire code. The problem is on entering a non integer in the field, the program halts and it force quits. I tried solving it by using the part of code I've commented out. My solution doesn't work, so any guidance would be helpful.
from tkinter import *
root = Tk()
def sarteg():
**#while True:
# try:
# a= int(e.get())
# except ValueError:
# eror= Label(root,text="Please enter an integer").pack()
# continue
# else:
# break**
a= int(e.get())
if a%2==0:
even=Label(root,text="number is even").pack()
else:
odd=Label(root,text="number is odd").pack()
label1= Label(root, text="Enter an Integer then click on \"FIND OUT\"").pack()
e = Entry(root, width=20)
e.pack()
mybutt= Button(root, text="find out", command=sarteg)
mybutt.pack()
root.mainloop()
I tried the code, it seems to working fine.
You had error on line 5.
You added 2 asterisks.
**#while True:
If you remove the asterisks, it's working fine. Comments can be added by just adding # before the line.
One more thing I'd recommend it to create a common label to show the results. Because every time you check the number a new label appears creating a list of results.
I believe all you really have to do is remove the while True statement. Try this:
def sarteg():
try:
a = int(e.get())
except ValueError:
eror = Label(root, text="Please enter an integer").pack()
return None
if a % 2 == 0:
even = Label(root, text="number is even").pack()
else:
odd = Label(root, text="number is odd").pack()
I wrote some simple code to describe my problem: I want to take an integer value from an entry to use it later.I tried also to use a spin box. here is my code:
from tkinter import*
win=Tk()
win.geometry('300x200')
e=Entry(width=10)
e.pack()
y=int(e.get())
print(y*2)
I always get the same error:
y = int(e.get())
ValueError: invalid literal for int() with base 10 ' '
I don't know why this is happening!
ValueError: invalid literal for int() with base 10 ' '
means that you are trying to convert the string "" to an integer. This, of course, is invalid. The reason you are trying to convert an empty string to an integer is that you are not allowing any value to be placed into the entry.
A good way to allow this to happen would be using a button, which calls a function to get the value within the entry and print it. Also, you are missing the line win.mainloop() which you would need at the end of your code.
Here is the example code you are probably asking for:
from tkinter import *
win = Tk()
win.geometry('300x200')
def printVal():
y = int(e.get())
print(y*2)
e = Entry(width=10)
e.pack()
b = Button(text="push me to print the value in e")
b.pack()
win.mainloop()
This code will still return errors if the value in the entry is not a valid integer, so if you want it to be robust, you'll have to play around with it.
there is several problems in your example, for example. in which moment you are trying to get value from Entry?
your code should looks something like:
from tkinter import *
def validate(value):
print (value)
try:
if value:
return int(value)
except:
return None
def calculate():
x = e1.get()
x_validate = validate(x)
if x_validate == None:
e1.delete(0, END)
e1.insert(0, 'you need to enter integer')
Label1.config(text='')
else:
result = x_validate*2
Label1.config(text=result)
win = Tk()
e1 = Entry(win)
e1.grid(row=0, column=0)
Button(win,text='Calculate', command = calculate).grid(row=0, column=1)
Label(win,text='Result').grid(row=1, column=0)
Label1 = Label(win)
Label1.grid(row=1, column=1)
win.mainloop()
Example if you enter integer and press calculate
Example if you enter string and press calculate
im beginner on python and as a practice i want to solve this ( https://www.practicepython.org/exercise/2014/07/05/18-cows-and-bulls.html ) by tkinter
when i run this code and press start button it hangs and no error is shown in pycharm, even when i debug
obviously the bug is in game code
can you help me with this?
from tkinter import *
import random
def entry_box():
global user_guess
start_button.destroy()
user_guess=Entry(win,font='Bradly 12', width=25)
user_guess.insert(END,'0000')
user_guess.place(x=150,y=150)
game()
def game():
global user_guess , result
digit=[]
num =[]
counter = 0
for i in range(4):
digit.append(random.randint(0,9))
while num != digit:
num = list(user_guess.get())
cow = 0
bull = 0
for i in range(4):
if int(num[i]) in digit:
if int(num[i])==digit[i]:
cow += 1
else:
bull += 1
counter += 1
result.set('cow = %d \n bull = %d'%(cow,bull))
result.set('WELL DONE! YOU FOUND IT AFTER %d GUESS ' %counter )
win = Tk()
win.title('Let\'s play')
frame = Frame(win, height=300, width=500, bg='lightblue')
frame.pack()
result = StringVar()
result.set('cow=0\nbull=0')
start_button = Button(win , text='start', font='Broadway 15',command = entry_box)
start_button.place(x=200, y=175)
results = Label(win, textvariable=result, font='Broadway 20',bg='lightblue', fg='darkblue')
results.place(x=200 , y=0)
win.mainloop()
Your code hangs because of multiple reasons:
as #furas mentioned, num != digit will always be False, because you compare list of chars with list of digits;
Even if you fix this, your code will just never exit the loop: you will compare the first list [0,0,0,0] with the random one (num) and unless they are equal, you will get False. Then the code takes the same two lists, and compares them infinitely, with always the same outcome. You can see this easily if you add a print statement in the while loop.
This is one possible solution:
import tkinter as tk
import random
class MainGame(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.main_frame = tk.Frame(self, height=300, width=500, bg='lightblue')
self.main_frame.pack()
self.result = tk.StringVar()
self.result.set("Cow=0\nBull=0")
self.start_button = tk.Button(self.main_frame, text='start', font='Broadway 15', command=self.entry_box)
self.start_button.place(x=200, y=175)
self.results = tk.Label(self.main_frame, textvariable=self.result, font='Broadway 20', bg='lightblue',
fg='darkblue')
self.results.place(x=200, y=0)
def entry_box(self):
self.start_button.destroy()
self.user_guess = tk.Entry(self.main_frame, font='Bradly 12', width=25)
self.user_guess.insert(tk.END, '0000')
self.user_guess.place(x=150, y=150)
self.start_game()
def start_game(self):
user_input = self.user_guess.get()
num = [int(cypher) for cypher in user_input]
counter = 0
game_playing = True
while game_playing is True:
digit = [random.randint(0, 9) for i in range(4)]
cow, bull = 0, 0
for i in range(4):
if num[i] in digit:
if num[i] == digit[i]:
cow += 1
else:
bull += 1
counter += 1
print("Turn {}: cows = {}\t bulls={}".format(counter, cow, bull))
if cow == 4:
print("digit = {}\t num = {}".format(digit, num))
game_playing = False
if __name__ == "__main__":
game = MainGame()
game.mainloop()
First thing: do not use global imports (from tkinter import *). Instead use import tkinter as tk.
Then let's look at your entry_box: the function as you defined it takes no argument, but then you expect it to delete the start_button: the only reason this works is because the function is defined in the same script, but as soon as you move it to another script for example, it will fail. You did the same with result, which is defined in the main body, but then used in game, and for the win variable used to set the user_guess Entry widget.
The solution for this is to 1) reformat your code to account for these changes, which can work for something this small 2) use global variables, but this is usually considered a bad practice, because as your code grows it becomes a pain to track them down (plus many other reasons) 3) use classes, which is what I did here.
So here is what I did: I create a class, and in the __init__ I put the things I want to have available when the script starts, or that I generally want to use throughout the game: the main frame where I will place the widgets, the results or the start button.
Then the entry_box function: You see that I pass just self: since the start button was defined as self.start_button in the __init__, there is no reason to pass it as an argument, because it is already stored in self as an attribute. Same with the main_frame where I put the Entry widget.
Lastly the game function: here, I make sure that the comparison between num and digit is between int numbers. Then if the comparison fails, I draw another random list of 4 elements for digit and repeat. The results are printed in the terminal.
This is by no means perfect, and you can easily improve it in a few ways:
1) the comparison between the lists can be easily made faster and shorter with numpy;
2) I did not update the results widget. You should be able to do it with what I told you here.
3) I assume you want the user to input the user_guess. You just have to modify a bit this code
Hope it helps!
I am new to python and this is the first project I am working on, it is a Litecoin - Euro conversion program. I had a problem, that if I did not put anything into the Entry() fields of the program and submitted it, the console would output following error message (because int() and float() cannot convert an empty string into an int/ a float):
Exception in Tkinter callback
Traceback (most recent call last):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1536, in __call__
return self.func(*args)
File "/Users/Samir/Library/Mobile Documents/com~apple~CloudDocs/Coding/Python/hello_world/exch.py", line 13, in exchange
choice = int( exc.get() ) # choice of EUR to LTC or other way around
ValueError: invalid literal for int() with base 10: ''
The whole code I used in that matter:
from Tkinter import *
from json import *
from urllib2 import *
def exchange():
data = urlopen('https://btc-e.com/api/3/ticker/ltc_eur') # EUR - LTC API
j_obj = load(data) #loads json data
exch = float( j_obj['ltc_eur']['avg'] ) # picks exchange rate out of api
choice = int( exc.get() ) # choice whether EUR to LTC or other way around
amount = float ( am.get() ) # amount of the currency the user wants to convert
if choice == 0:
print round((1 / exch) * amount, 2), "Litecoins"
elif choice == 1:
print round(exch * amount, 2), "Euro"
else: # if something other than 0 or 1 was typed in
print "I'm sorry but you have to enter either 0 or 1"
am.delete(0, END)
exc.delete(0, END)
master = Tk() # creates new window in var master
master.wm_title("LTC - EUR converter") # creates title for the window
Label(master, text = "EUR into LTC (0) or LTC into EUR(1): ").grid(row = 0, sticky = W) # creates choice string in a table (Row 1)
Label(master, text = "Amount: ").grid(row = 1, sticky = E) # creates text "Amount" in a table (Row 1)
exc = Entry(master) # picks up Entryvalue
exc.grid(row = 0, column = 1)
am = Entry(master) # picks up Entryvalue
am.grid(row = 1, column = 1) # places it at row 0 colum 1 in the table
Button(master, text = "Quit", command = master.quit).grid(row = 2, column= 1, sticky = W) # creates a quit button that closes the window
Button(master, text = "Submit", command = exchange).grid(row = 2, column = 1) # creates a submit button that executes def "exchange"
mainloop() # starts the program
I managed to fix the problem with changing the if query to comparing the input to strings and converting the input (to int and float) after it confirmed either 0 or 1 has been typed in.
The changed code:
choice = exc.get()
amount = am.get()
if choice == '0':
choice = int(choice)
amount = float(amount)
print round((1 / exch) * amount, 2), "Litecoins"
elif choice == '1':
choice = int(choice)
amount = float(amount)
print round(exch * amount, 2), "Euro"
else:
print "I'm sorry but you have to enter either 0 or 1"
So my question is, is there any solution for that problem that is more efficient? Because I think my approach works but it isn't the best option out there.
"It is better to ask for forgiveness than permission".
You can place your code in a try-except block.
try:
choice = int(choice)
amount = float(amount)
except ValueError:
print "I'm sorry but you have to enter either 0 or 1"
return
if choice == 1:
...
else:
...
This way, you check the value of choice once rather than twice.
Edit: If would be prudent to keep separate try-except braces for choice and amount. With the current scenario, entering a valid choice but an invalid amount could yield a misleading error message.
Trying to get used to the tkinter gui but I'm running into a problem with setting up an input box. I wanted to make a simple number guessing program using Entry to input an integer and a button to submit the guess. I'm getting an str to int conversion error when I use int(GuessBox.get()) and I'm not sure what to do.
ValueError: invalid literal for int() with base 10: ''
from tkinter import *
import random
def makeAGuess():
guess = int(GuessBox.get())
print(guess)
if guess == Answer:
print("you got it!")
return False
elif guess > Answer:
print("Too High, try again")
return True
else :
print("Too low, try again")
return True
Answer = random.randint(1, 100)
main = Tk()
label = Label(main, text = "Guess a number")
label.pack()
GuessBox = Entry(master = main)
GuessBox.pack()
submitGuess = Button(master = main, text = "Submit Guess", command = makeAGuess())
submitGuess.pack()
main.mainloop()
You need to pass the function as an object, don't call it.
submitGuess = Button( master = main, text = "Submit Guess", command = makeAGuess )
Otherwise makeAGuess is called when the Button is created, but not passed any arguments.
With this change your code works perfectly for me.