On the Forum there has recently been posted a Question by #Clueless_captain; it was answered by #furas. I am new to stackoverflow so I can not comment in that Conversation. This is the URL to that Conversation: (Tkinter Entry widget stays empty in larger programs (Python 2)). The Code posted by furas is not exactly what I try to do, but the only Thing I can not do myself is finding a way to re-use the Input that has been given in the EntryWidget. I modified the Code written by furas; my Goal was that the Input would be printed before the GUI terminated. For that I bound the Return key to a new Function, this Function was supposed to get the Textstring in this new Function where it would further be processed. It does only do that when I click the Button to get a name for a second time. Is the order of this Code off? I believe the Issue is closely related to the String 'e.bind' on line ten, but I can not find the Issue.
Best Regards, G_Lehmann
---------- The modified code:
from Tkinter import *
def get_input(text, variable):
win = Toplevel()
win.title("Get value")
f = LabelFrame(win, text=text)
f.pack()
e = Entry(win, textvariable=variable)
e.bind("<Return>", do_more(text, variable, e))
e.pack(side="right")
#I tried e.bind here, but This had no Effect.
b = Button(win, text = "Cancel", command=win.destroy)
b.pack()
#do_more is the new Function I want to use to process the Variable 'data' further.
def do_more(text, variable, e):
data = e.get()
print data
print len(data)
print type(data)
def get_value(text, variable):
get_input(text, variable)
# --- main --
root = Tk()
root.title("Ask-name-SUB")
# global variables
var_name = StringVar()
var_address = StringVar()
b = Button(root, text="Enter your name", command=lambda: get_value("Your name:", var_name))
b.pack()
b = Button(root, text="Enter your address", command=lambda: get_value("Your address:", var_address))
b.pack()
b = Button(root, text="Cancel", command=root.destroy)
b.pack()
root.mainloop()
# --- after -- (My Edit: I disabled this as I want to bind the Variables before my GUI gets terminated)
"""
name = var_name.get()
print "Print name, its length, its type"
print name, len(name), type(name)
address = var_address.get()
print "Print address, its length, its type"
print address, len(address), type(address)
"""
bind expects function name (like in command=) so you have to use lambda to assign function with arguments. Besides bind execute function with argument event so you have to receive it.
e.bind("<Return>", lambda event:do_more(variable))
You can assign do_more to button too
b = Button(win, text="OK", command=lambda:do_more(variable))
and do the same with Return and with Button - and close window after do something with variable.
You can also do the same in get_value after you close window but you have to use win.wait_window() because normally tkinter create window and doesn't wait till you close it.
So now you have two possibility to do something with value - in do_more or in get_value - choose one. Both method can be modify - ie. you can use class and create own dialog window.
from Tkinter import *
# --- ---
# global variable to use in different functions
win = None
def get_input(text, variable):
global win # inform function to use global variable `win` to assign value
win = Toplevel()
win.title("Get value")
f = LabelFrame(win, text=text)
f.pack()
# use `f` instead of `win` to put inside LabelFrame
e = Entry(f, textvariable=variable)
e.pack()#side="right")
e.bind("<Return>", lambda event:do_more(variable))
b = Button(win, text="OK", command=lambda:do_more(variable))
b.pack()
def do_more(variable):
data = variable.get()
print 'do_more:', data, len(data), type(data)
win.destroy()
# --- ---
def get_value(text, variable):
# create window
get_input(text, variable)
# this code is executed directly after creating window, not after closing window
# so code has to wait till window is closed
win.wait_window()
data = variable.get()
print 'get_value:', data, len(data), type(data)
# --- main --
root = Tk()
root.title("Ask-name-SUB")
# global variables
var_name = StringVar()
var_address = StringVar()
b = Button(root, text="Enter your name", command=lambda:get_value("Your name:", var_name))
b.pack()
b = Button(root, text="Enter your address", command=lambda:get_value("Your address:", var_address))
b.pack()
b = Button(root, text="Cancel", command=root.destroy)
b.pack()
root.mainloop()
Related
I'm trying to make a basic interest income calculator using GUI tkinker in Python. However, after entering all the values, the label at the end doesn't update.
Please note that calculations is just printing the variables for now
import tkinter as tk
frame = tk.Tk()
frame.title("Interest Income Calculator")
frame.geometry('800x450')
label = tk.Label(text="Enter Balance (number, no symbols)")
entry = tk.Entry(fg="Black", bg="White", width=50)
label.pack()
entry.pack()
def update1():
global balance
balance = entry.get()
buttonupdate1 = tk.Button(
text = "Save")
buttonupdate1.pack()
buttonupdate1.config(command = update1())
label2 = tk.Label(text="Enter Standard Interest (percentage but no symbol)")
entry2 = tk.Entry(fg="Black", bg="White", width=50)
label2.pack()
entry2.pack()
def update2():
global sinterest
sinterest = entry2.get()
buttonupdate2 = tk.Button(
text = "Save")
buttonupdate2.pack()
buttonupdate2.config(command = update2())
label3 = tk.Label(text="Enter Bonus Interest (percentage but no symbol)")
entry3 = tk.Entry(fg="Black", bg="White", width=50)
label3.pack()
entry3.pack()
def update3():
global binterest
binterest = entry3.get()
buttonupdate3 = tk.Button(
text = "Save")
buttonupdate3.pack()
buttonupdate3.config(command = update3())
button = tk.Button(
text="Calculate",
width=25,
height=1,
background="white",
foreground="black",
)
button.pack()
calculations = (balance, sinterest, binterest)
label4 = tk.Label(
text = (calculations),
foreground = "black",
background="white",
width=25,
height=10
)
def cont():
label4.pack()
button.config(command=cont())
frame.mainloop()
I've tried so many things, like moving around the functions etc. with no luck. please help
To understand why it doesn't work when we use command = func() we have to understand how passing function as an argument works
When we pass function with parentheses as an argument, we are first calling the function and then giving the returned value as an argument for the method or function we are using. For example
def sum():
return 1 + 1
example1 = sum
example2 = sum()
# -> example1 is a function object
# -> example2 is 2
This is why in your code you have to give your button a function object rather than the return value of the function so it can run the function object when you press the button.
I ran your code with these fixes and noticed it doesn't run. This is because in your code you are defining your variables sinterest, balance and binterest inside your functions and it throws an error because now you don't run the functions when the code runs.
Also you are trying to change values inside tuple, which is impossible since tuples are immutable
calculations = (balance, sinterest, binterest)
You should change it to a list, because you can change the value inside list
calculations = [balance, sinterest, binterest]
(command = function) because you are passing the function not calling the function()
There's an example of my code below.
I am trying to make a GUI with tkinter, in python. I want an app that has a variable, let's say var_list, that is introduced into a function as a parameter.I run this function using a button with command=lambda: analize(var_list)
I want to be able to modify the variable by pressing buttons (buttons to add strings to the list). And I have a function for that aswell:
def button_clicked(e):
if ((e["text"]).lower()) in var_list:
var_list.pop(var_list.index((e["text"]).lower())) #this adds a string to the list
else:
var_list.append((e["text"]).lower()) #this deletes the string from the list if it was already there
The function works, I tried printing the var_list and it gets updated everytime I press a button.
The problem is that I have to create the var_list as an empty list before, and when I run the function analize(var_list), it uses the empty list instead of the updated one.
Any idea on how to update the global var everytime I add/delete something from the list?
from tkinter import *
from PIL import ImageTk
def show_frame(frame):
frame.tkraise()
def button_clicked(e):
if ((e["text"]).lower()) in var_list:
var_list.pop(var_list.index((e["text"]).lower()))
else:
var_list.append((e["text"]).lower())
def analize(x):
#does stuff with the list
window = Tk()
frame1 = Frame(window)
frame2 = Frame(window)
canvas1 = Canvas(frame1,width = 1280, height = 720)
canvas1.pack(expand=YES, fill=BOTH)
image = ImageTk.PhotoImage(file="background.png")
var_list = []
button1 = Button(canvas1, text="Analize",font=("Arial"),justify=CENTER, width=10, command=lambda: [show_frame(frame2),analize(x=var_list)])
button1.place(x=(1280/2)-42, y=400)
button2 = Button(canvas1, text="String1",font=("Arial"),justify=CENTER, width=10, command=lambda: button_clicked(button2))
button2.place(x=(1280/2)-42, y=450)
button3 = Button(canvas1, text="String2",font=("Arial"),justify=CENTER, width=10, command=lambda: button_clicked(button3))
button3.place(x=(1280/2)-42, y=500)
Thank you
you can make a global variable eg:-global var
Now you can access it within other defination to manipulate the variable like this
global var
var = 0 # if you want to set a default value to the variable before calling the
function
def change_var():
global var
var = 1
USE OF GLOBAL
using global is highly recommended and is quite necessary if you are working with functions that contain or has the need to manipulate the variable
If global is not given inside the function, the variable will live inside the function and it cannot be accessed outside the function.
Hope this answer was helpful, btw, I am not sure if this the answer you are looking for as your question is not clear, maybe give a situation where you might think it might be necessary to change or update the variable
Sorry, I did not understand you but I guess this example will help you -
import tkinter as tk
root = tk.Tk()
var_list = []
def change_val(n):
var_list.append(n)
label1.config(text=var_list)
def remove():
try:
var_list.pop()
label1.config(text=var_list)
except:
pass
label1 = tk.Label(root,text=var_list)
label1.pack()
button1 = tk.Button(root,text='1',command=lambda:change_val(1))
button1.pack()
button2 = tk.Button(root,text='2',command=lambda:change_val(2))
button2.pack()
button3 = tk.Button(root,text='3',command=lambda:change_val(3))
button3.pack()
button4 = tk.Button(root,text='Pop Element',command=remove)
button4.pack()
root.mainloop()
I am new to codding in general. I have found a code for a function which restricts users of entering anything but digits in entry field but I can't assign the function to entry object.
I have tree problems.
I can't assign function to entry.
I want error print message to show in label "A".
Pressing "Enter" multiple times execute "def doit(FFF)" multiple times on top of each other, so I want to restrict pressing it more than one time.
I have been trying for the past 3 days but I keep failing.
from tkinter import *
def doit(FFF):
...
def val():
API = IN.get()
while True:
try:
API = int(input())
except ValueError:
print('Not an integer')
continue
else:
return API
break
root = Tk()
root.geometry("300x200")
IN = Entry(root)
IN.bind("<Return>", val, lambda _:doit(FFF))
IN.pack(side=LEFT, fill="both", expand=True)
A = Label(root, fg="red")
A.pack(side=LEFT)
B = Button(root, text="START", fg="black", command=lambda:doit(FFF))
B.pack(side=RIGHT)
root.mainloop()
Example
is_integer() checks only if text is integer number and returns True/False so it can be used in many places.
<KeyRelease> executes validate() after every keypress (or rather key release) and validate() uses is_integer() to check text in Entry (event.widget gives access to widget to which was bind() event) and changes text in Label.
Button executes function run_it() which uses is_integer() to check if Entry has correct integer (to make sure) or you have to check if Entry is not empty. If Entry has no correct integer then it changes text in Label and ends function.
import tkinter as tk
# --- functions ---
def run_it():
# you can check it again to make sure
text = e.get()
if not is_integer(text):
l['text'] = "You can't run it"
return
# do what you want
l['text'] = 'Running ...'
def validate(event):
#text = e.get()
text = event.widget.get()
if is_integer(text):
l['text'] = ''
else:
l['text'] = 'Not an integer'
def is_integer(text):
try:
value = int(text)
return True
except ValueError:
return False
# --- main ---
root = tk.Tk()
e = tk.Entry(root)
e.pack()
#e.bind("<Return>", validate)
e.bind("<KeyRelease>", validate)
l = tk.Label(root)
l.pack()
b = tk.Button(root, text="START", command=run_it)
b.pack()
root.mainloop()
In the program I made, the user presses enter and the text typed is then shown as a label in the program. So the label keeps getting updated and then written on the next line. The problem is that in the textbox the previous line the user typed stays there, which means u have to keep manually deleting the string in the textbox to write a new line. How can I make it so that you start out with a cleared textbox? Also, the enter button works but it seems that when i click on the "Return" button it gives me an error:
TypeError: evaluate() missing 1 required positional argument: 'event'
Here's the code:
from tkinter import *
window = Tk()
window.geometry("200x300")
def evaluate(event):
thetext = StringVar()
labeloutput = Label(app, textvariable = thetext)
n = e.get()
thetext.set(n)
labeloutput.grid()
app = Frame(window)
app.pack()
e = Entry(window)
e.pack()
b= Button(window, text="Return", command=evaluate)
b.pack()
window.bind("<Return>", evaluate)
mainloop()
Since you bind evaluate as a callback and you use it as a button command, when you use it in the button you have to use a lambda and pass None to the event. event argument is needed because of the binding, but there is no event when you call it from button click, so just pass None to get rid of the error. You can delete by doing entry.delete(0, 'end').
from tkinter import *
window = Tk()
window.geometry("200x300")
def evaluate(event):
thetext = StringVar()
labeloutput = Label(app, textvariable = thetext)
n = e.get()
thetext.set(n)
labeloutput.grid()
e.delete(0, 'end') # Here we remove text inside the entry
app = Frame(window)
app.pack()
e = Entry(window)
e.pack()
b = Button(window, text="Return", command=lambda: evaluate(None)) # Here we have a lambda to pass None to the event
b.pack()
window.bind("<Return>", evaluate)
mainloop()
Of course, if you want to prevent the lambda from being used, you would have to create a function to handle the key binding, and a separate one for the button click.
I am new to Tkinter and not to sure how to proceed. I am trying to link a function that I define to a entry widget that is activated by a button. but I can't figure out how to get the three to communicate to each other. I would like it to print as well as return to the script so that I can be used in another function. This is what I have so far:
import Tkinter as tk
def TestMath(x):
calculate = x + 4
print calculate
return calculate
root = tk.Tk()
entry = tk.Entry(root)
value = entry.get()
number = int(value)
button = tk.Button(root, text="Calculate")
calculation = TestMath(number)
root.mainloop()
Button calls function assigned to command= (it has to be "function name" without () and arguments - or lambda function)
TestMath assigns calculation to global variable result and other functions can have access to that value.
import Tkinter as tk
def TestMath():
global result # to return calculation
result = int(entry.get())
result += 4
print result
result = 0
root = tk.Tk()
entry = tk.Entry(root)
entry.pack()
button = tk.Button(root, text="Calculate", command=TestMath)
button.pack()
root.mainloop()
Function called by button don't have to return value because there is no object which could receive that value.