How to use .get() within a function. Python - python

from Tkinter import *
import random
def Factorer(a,b,c):
while True:
random_a1=random.randint(-10,10)
random_a2=random.randint(-10,10)
random_c1=random.randint(-10,10)
random_c2=random.randint(-10,10)
if random_a1==0 or random_a2 == 0 or random_c1 == 0 or random_c2 == 0:
pass
elif (random_a1*random_c2) + (random_a2*random_c1) == b and random_a1/random_c1 != random_a2/random_c2 and random_a1*random_a2==a and random_c1*random_c2==c:
break
print "y=(%dx+(%d))(%dx+(%d))" % (random_a1,random_c1,random_a2,random_c2)
root = Tk()
buttonSim1 = Button(root, text="Convert", command=lambda: Factorer(enterA.get(),enterB.get(),enterC.get()))
buttonSim1.grid(row=2, column=3)
enterA = Entry(root)
enterA.grid(row=1, column=1)
enterB = Entry(root)
enterB.grid(row=1, column=2)
enterC = Entry(root)
enterC.grid(row=1, column=3)
root.mainloop()
How can I get this code to run, every time I click the button It just crashes.
It works however if I remove the .get() and just insert numbers.
Thanks in advance

You are comparing strings to ints, you would need to cast a,b and c to int:
Tkinter.Button(root, text="Convert", command=lambda: Factorer(int(enterA.get()),int(enterB.get()),int(enterC.get())))

The root of the problem is that you're comparing strings to integers, so your infinite while loop never finishes. That is why the program hands and has to be force-quit.
The best solution is to have your button call a function that gets the data, formats it to the proper value, and then calls the function to do the work. Trying to squeeze all of that into a lambda makes for a program that is hard to debug.
For example:
def on_button_click():
a = int(enterA.get())
b = int(enterB.get())
c = int(enterC.get())
result = Factorer(a,b,c)
print(result)
Tkinter.Button(..., command=on_button_click)
By using a separate function, it gives you the opportunity to add print statements or pdb breakpoints so you can examine the data as it is running. It also makes it easier to add try/catch blocks to handle the case where the user didn't enter valid numbers.

Related

I am working on my first tkinter project and i need some guidance

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()

taking an integer value from an entry widget in tkinter

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

How to fix the game function?

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!

Converting a script into GUI using Tkinter

I really need help, I have written a script that implements a flow equation. The problem is that i would love to convert this to a GUI, I am a student and i am meant to submit this assignment anytime soon, i don't have time for learning Tkinter now but i will surely learn it next month. the script below:
print ("this program measures gas flowrate in pipes with effect of elevation, making use of USCS unit")
e=2.718
Tb=520
Pb=14.7
f=float(input("Friction factor,f: "))
P1=float(input("upstream pressure,P1: "))
P2=float(input("downstream pressure,P2: "))
G=float(input("gas gravity,G: "))
Tf=float(input("average gas flowing temperature,Tf: "))
L=float(input("pipe line segment,L: "))
Z=float(input("gas compressibility factor at flowing temperature,Z: "))
D=float(input("pipe inside diameter,D: "))
H1=float(input("upstream elevation,H1: "))
H2=float(input("downstream elevation,H2: "))
s=float((0.0375*G)*((H2-H1)/(Tf*Z)))
j=float((e**s-1)/s)
Le=float(L*j)
F=float(2/f**0.5)
Q=38.77*F*(Tb/Pb)*((P1**2-(e**s*P2**2))/(G*Tf*Le*Z))**0.5*D**2.5
print(j);
print(s);
print(Q);
Thanks alot for assistance
First, import tkinter and create the main object:
import Tkinter as tk
master = tk.Tk()
Then create inputs that will go in the main window. For each input, create a label and an entry for the input:
Example:
L1 = tk.Label(master, text="friction factor, f: ")
L1.pack()
L1.grid(row=0, column=0)
E1 = tk.Entry(master, bd =5)
E1.pack()
E1.grid(row=0, column=1)
# .... all other labels and input entries
# And a label for the result:
result = tk.Label(master)
result.pack()
Then, get all values from the entries to variables, for example:
f = float(E1.get())
Add a button to press for calculation:
button = tk.Button(master, text='Calculate', command=calculate)
button.pack()
# calculate is a function that you will define, that gets all values from the input and returns the final value. Send also the result label to the function to change the text of the result label.
def calculate(result, f, .....):
# Your calculating algorithem
output = "j: " + str(j) + ", Q: "+ str(Q) + ", s: "+str(s)
result.config(text=output)
In the end of your code, you will have this line that runs the window:
master.mainloop()
If you need further explanation, please write.

TypeError: get() missing 1 required positional argument: 'self' - NOT USING CLASS - Python 3.5

due to my crude knowledge of Python, I am expecting more mistakes with the following script than just the positional argument error. Hence, I would very much appreciate any and all kind of observations/corrections. Again, I would like, if at all possible, to fix the positional argument error without having to use class. Thank you all very much.
# Python 3.5.1
from tkinter import *
from tkinter import ttk
root = Tk()
root.geometry("300x200+150+50")
total = 0.0
amount = 0.0
n = 0
x = 0
def total_amount():
total = Entry.get()
print ('got total!')
lb=ttk.Label(root, text="Enter total").grid(row=n, column=1)
totalEnt=ttk.Entry(root).grid(row=n, column=2)
button=ttk.Button(root, text='ok', command=total_amount).grid(row=n, column=3)
if total !=0:
while True:
if amount < total:
while True:
n = n + 1
if x == 0:
def amount_entered(event):
amount = amount + Entry.get()
x = x + 1
print ('got amount!')
lb=ttk.Label(root, text="Enter amount").grid(row=n, column=1)
amountEnt=ttk.Entry(root).grid(row=n, column=2)
button=ttk.Button(root, text='Ok', command=amount_entered).grid(row=n, column=3)
elif x != 0:
print ('gone from internal loop!')
break
elif sub == total:
print ('done!')
break
else:
print ('sum of amount(s) cannot be greater than total')
else:
pass
root.mainloop()
You're getting the error message because .get() won't work on the class Entry. It will work on an object such as totalEnt that is an instance of Entry.
So you need
total = totalEnt.get()
Also, something like
totalEnt=ttk.Entry(root).grid(row=n, column=2)
won't work. If you need to give a name to an object such as totalEnt, you need to create it first, then call grid on it.
totalEnt=ttk.Entry(root)
totalEnt.grid(row=n, column=2)
You don't necessarily have to write any of your own classes, but to use tkinter (or probably any gui package in a object oriented language) you have to use some of the classes that are part of it. When you do something like
totalEnt=ttk.Entry(root)
You are creating an object, totalEnt, which is an instance of the class ttk.Entry. You imported the class from tkinter.

Categories

Resources