Python3 Tkinter, how do I get a variable inside of a def? - python-3.x

I'm trying to get the variable "user_get" inside the def entered(user_input)
import tkinter as tk
from tkinter import ttk
window = tk.Tk()
#put settings in place (username input)
window.geometry('1920x1080')
window.configure(bg = 'blue')
def entered(user_input):
user_get = user_input.widget.get()
user_input.widget.delete(0, 'end')
print(user_get)
return user_get
user_input.widget.destroy()
# TextBox (input)
user_input = tk.Entry(window)
user_input.pack()
user_input.place(x = 100,y = 40)
user_input.bind("<Return>", entered)
thing = user_get
print(thing)
window.mainloop()
I have tried:
-return (I don't really understand it that well)

Here I've made it so the user_input variable is available in the global scope. The global keyword in the entered function allows that function to modify the global variable. Now, when you type into the entry and hit Return, the value of user_input is updated.
I defined an example function that will print this value whenever a button is pressed. Note that until you add text to the Entry and press Return, an empty string will be printed!
Likewise, any calls like print(user_input) made immediately before root.mainloop() will print an empty string because the value of user_input hasn't been updated yet.
import tkinter as tk
def entered(_event):
global user_input # allow this function to modify this variable
user_input = entry.get() # update the variable with the entry text
entry.delete(0, 'end') # clear entry contents
def use_value_from_entry():
"""Example function to use the value stored in 'user_input'"""
print(user_input)
window = tk.Tk()
user_input = '' # create a variable to store user input in the global scope
entry = tk.Entry(window) # create the entry widget
entry.pack() # add the widget to the UI
entry.bind('<Return>', entered) # bind the event handler
# this button runs an example function to get the current value of 'user_input'
button = tk.Button(window, text='Click Me', command=use_value_from_entry)
button.pack()
window.mainloop() # run the app
#Stockmage updated this

Related

How to check if the entry widget is empty, if it only takes int values

I am creating a GUI with tkinter for my Password Generator App, in which I included is entry widget in which the users can enter the length of the password to be generated.
If the user does not enter any value(only integer) in the entry box I want to raise an error with messagebox.showerror. How can i check whether the entry box is empty or not?
Solution:
You will need to get the value inside the Entry and store it into a variable.
Then check the variable's length(using len) and put a condition that if its length is 0, That means the Entry is empty, then you can display an error message.
After you have checked its length, you can now convert it into an integer.
Like in this Example:
import tkinter as tk
from tkinter import messagebox
def check():
var = e.get()
if len(var) == 0:
messagebox.showerror('Error', 'Entry is empty')
else:
pass
var = int(var)
root = tk.Tk()
e = tk.Entry(root)
e.pack()
b = tk.Button(root, text='check', command=check)
b.pack()
root.mainloop()

Why printing out e_name.get() works, but printing the variable assignment to this same .get() doesn't?

I'm trying to get a name from an user with Entry() function from Tkinter and then assign it to the variable Name, so that I can use it later. To check if the assignment works, I call the ready function, which makes Label with my variable. When i use 'e_name.get()' in 'command=' it works but when i use 'name' it doesn't. I guess I've messed up in order of code lines, but I'm not sure.
Here is the python code:
from tkinter import *
root = Tk()
e_name = Entry(root, width=50)
e_name.pack()
name = e_name.get()
def ready():
test = Label(root, text= name) #and this works >>> test = Label(root, text= e_name.get())
test.pack()
ready_button = Button(root, text="Next", command=ready)
ready_button.pack()
root.mainloop()
Declare name as global to access it outside of ready() function:
1) Initialize name = '' before def ready()
2) Add global name as first line in ready()
3) Add a new Get Name button
4) Add a new label below Get Name button to display the global name variable upon clicking Get Name button
5) Add function get_name() which uses global name to configure the new label with the last value stored by the ready() function.
It isn't pretty, but this working code demonstrates how to use name outside of ready function thanks to global. Test it by editing entry value, clicking Next button, then clicking Get Name button. The Get Name clicks will change the label directly under it to reflect the last value stored in global name by the ready() function.
If you edit the entry value and press the Get Name button it will not display the new value (it will continue to show previous value) in the new label until you click the Next button, because that is where global name variable is changed. I think this is the behavior you desire:
Here is the full working code:
from tkinter import *
root = Tk()
e_name = Entry(root, width=50)
e_name.pack()
name = ''
def ready():
global name
name = e_name.get()
test = Label(root, text= name) #and this works >>> test = Label(root, text= e_name.get())
test.pack()
def get_name():
global name
test2.configure(text= name)
ready_button = Button(root, text="Next", command=ready)
ready_button.pack()
name_button = Button(root, text="Get Name", command=get_name)
name_button.pack()
test2 = Label(root)
test2.pack()
root.mainloop()

How can a function change a global variables (Tikinter example)?

I am new in Oython. I wrote a simple calculator I can't understand How the function that we called it to "evaluate" works.
I have known that we have the local variables in the functions and the functions cant change the variables outside the function except we define it as output,
But in this function, It changes an outside variable and defines a new label.
I expect that we input ans as an input and take an output. and another strange problem is that we didn't give e as input but this function takes variable e with e.get() comment. How does the function know that we have a variable e when we didn't give it to the function,
My second question is how does "configure" work?
This is my code:
from tkinter import*
root=Tk()
label1 = Label(root,text="Enter your expression:")
label1.pack()
def evaluate(event):
data=e.get()
ans.configure(text="Answer:"+ str(eval(data)))
e = Entry(root)
e.bind("<Return>",evaluate)
e.pack()
ans = Label(root)
ans.pack()
root.mainloop()
The reason your function works is because Python is someone accepting of this situation.
Python will first try to edit a local variable when it cannot find ans as a local variable it then assumes it must be in the global name space and then checks there. This does not always work but can if the condition are right.
Here is a code example that shows where the function will guess correctly that your variable is in global and one function that fails at it.
import tkinter as tk
root = tk.Tk()
def print_some_number():
some_number = some_number + 5
print(some_number)
def testing():
lbl.configure(text="After button press")
some_number = 5
lbl = tk.Label(root, text="Before button press")
lbl.pack()
tk.Button(root, text="Update lavel", command=testing).pack()
tk.Button(root, text="Print some number", command=print_some_number).pack()
root.mainloop()
The print statement function will fail because we try to assign a local variable before assignment. We know it has been assigned in global but the function wont check because it looks like we are trying to assign it locally. The way to fix this is by adding the global statement like below:
import tkinter as tk
root = tk.Tk()
def print_some_number():
global some_number # global added here for this kind of fuction
some_number = some_number + 5
print(some_number)
def testing():
lbl.configure(text="After button press")
some_number = 5
lbl = tk.Label(root, text="Before button press")
lbl.pack()
tk.Button(root, text="Update lavel", command=testing).pack()
tk.Button(root, text="Print some number", command=print_some_number).pack()
root.mainloop()

tkinter, button returns variable

I am trying to make a GUI text based adventure game in python. I want to be able to take text from a textinput box and store it as string variable.
I have 2 problems:
Making the python wait for the submit button to be pressed, before
processing the input and updating the game.
Getting the text variable out of the command, I would like to not
use global if possible.
Here is some of my code to better understand:
root = tk.Tk()
root.geometry('800x600+100+100')
root.title("my game")
textbox = tk.StringVar()
textboxentry = tk.Entry(root, textvariable=textbox, bd=5, width = "40", font=("times", 20))
textboxentry.pack(in_=bgImageLabel, side = "bottom")
def getInput():
textboxInput = textbox.get() #gets entry
lengthEntry = len(textbox.get())
textboxentry.delete(0,lengthEntry) #removes entry from widget
return textboxInput # I would like this return to work
submit = tk.Button(root, text ="Submit", command = (textboxInput = getInput()))
##I want the command function to use command = getInput and store the return on getInput as textboxInput. This will update the wait_variable down below, and give the inputs(textboxInput) a string to work with.
submit.pack(in_=bgImageLabel, side = "bottom")
while game == True:
root.update_idletasks()
root.update()
submit.wait_variable(textboxentry)
## I need it to wait before proceeding to this next line because i need the textboxInput from the entry widget.
actionInput, extraInput, texts = inputs(textboxInput)
Currently I can't figure a way to use command = (textboxInput = getInput), using lambda or anything else. I just want to store the return which comes off of the Entry as a string variable that can be used by the main function.
All help is appreciated!
Below code processes entry widget's text when Submit button is pressed.
import tkinter as tk
root = tk.Tk()
aVarOutside = 'asd'
def btn_cmd(obj):
#use global variable
global aVarOutside
#print its unmodified value
print("aVarOutside: " + aVarOutside)
#modify it with what's written in Entry widget
aVarOutside = obj.get()
#modify lblTextVar, which is essentially modifying Label's text as lblTextVar is its textvariable
lblTextVar.set(obj.get())
#print what's inside Entry
print("Entry: " + obj.get())
txt = tk.Entry(root)
txt.pack()
lblTextVar = tk.StringVar()
lbl = tk.Label(root, textvariable=lblTextVar)
lbl.pack()
btn = tk.Button(text="Submit", command=lambda obj = txt : btn_cmd(obj))
btn.pack()
root.mainloop()
When the button is pressed:
Value of a global variable, aVarOutside is printed.
Value of aVarOutside is modified to the value of Entry box's
(txt's) content.
Value of a textvariable used by a label (lbl) is modified. Which
means that the text of lbl is updated and can be seen on the GUI.
Finally Entry box, txt's content is printed.
I think you should use inputs() inside getInputs() and then button doesn't have to return any variables - and then you can use root.mainloop() instead of while loop.
import tkinter as tk
# --- functions ---
def inputs(text):
# do something with text
print(text)
# and return something
return 'a', 'b', 'c'
def get_input():
global action_input, extra_input, texts
text = textbox.get()
if text: # check if text is not empty
textbox.set('') # remove text from entry
#textbox_entry.delete(0, 'end') # remove text from entry
action_input, extra_input, texts = inputs(text)
# --- main ---
root = tk.Tk()
textbox = tk.StringVar()
textbox_entry = tk.Entry(root, textvariable=textbox)
textbox_entry.pack()
submit = tk.Button(root, text="Submit", command=get_input)
submit.pack()
root.mainloop()
BTW: you could better organize code
all functions before main part (root = tk.Tk())
PEP8 suggests to use lower_case_names for functions and variables (instead of CamelCaseNames)
global is not prefered method but I think it is better solution than yours.
If you don't need global then you can use classes with self.
import tkinter as tk
# --- classes ---
class Game:
def __init__(self):
self.root = tk.Tk()
self.textbox = tk.StringVar()
self.textbox_entry = tk.Entry(self.root, textvariable=self.textbox)
self.textbox_entry.pack()
self.submit = tk.Button(self.root, text="Submit", command=self.get_input)
self.submit.pack()
def run(self):
self.root.mainloop()
def inputs(self, text):
# do something with text
print(text)
# and return something
return 'a', 'b', 'c'
def get_input(self):
text = self.textbox.get()
if text: # check if text is not empty
self.textbox.set('') # remove text from entry
#textbox_entry.delete(0, 'end') # remove text from entry
self.action_input, self.extra_input, self.texts = self.inputs(text)
# --- functions ---
# empty
# --- main ---
app = Game()
app.run()

How to know which Entry has been clicked?

I have a program that creates entry widgets using a for loop:
from tkinter import *
root = Tk()
entList = []
def deleteChar(event):
ent.delete(0, 'end')
ent.insert(0, '')
ent.config(fg='black')
for x in range(12):
ent = Entry(root, fg='grey60')
ent.insert(0, 'Enter Name')
ent.pack()
ent.bind('<FocusIn>', deleteChar)
entList.append(ent)
root.mainloop()
Is there any way to make the function recognize which entry has been clicked so it will delete the text in that one instead of only the last one created?
Exactly one widget in an application will have keyboard focus. You can query for which widget has the focus. In addition, the event object that is passed in has a reference to the widget that triggered the callback, which is typically what you do in an event callback.
def deleteChar(event):
event.widget.delete(0, 'end')
event.widget.insert(0, '')
event.widget.config(fg='black')

Resources