I am new to Tkinter, I have the following code:
from Tkinter import *
root = Tk()
root.title("Email Sender")
Label(root, text="To").grid(row=0)
text = StringVar()
toText = Entry(root, textvariable=text)
s= text.get()
root.mainloop()
My goal is to create a label "To" and an entry, I am trying to capture whatever typed from keyboard in the entry. However, with the above code, I got empty when I print s.
So how could I capture the text typed into the entry?
Thanks.
You are capturing the text typed into the Entry—but you're only doing s = text.get() once, before the mainloop has even started, at which point the text typed into the Entry is whatever the initial value of the Entry was, which is the empty string.
What you need to do is add an event handler that runs at the appropriate time—maybe on the root's close event, or each time the Entry's text is edited, or whatever seems right to you—and does the s = text.get(). Then, you'll have whatever was in the Entry at the time that event was fired.
Related
I started literally a couple of days ago, and I need help :(
I want to create a program to translate a phrase to something else
Ex:
Program
000000000000000000000000000000000000000000
"Phrase to translate"
(Here the person writes the sentence)
A button to activate the command
(And here the translated phrase appears)
000000000000000000000000000000000000000000
Or something like that
I already have the code to change the words, and I am creating the interface, and I have already learned to create windows but I still don't know how to paste my translation :(
This is what I have
frase=input("Escribe la frase: ")
entrada="abcdefghilmnopqrstuvxyz"
salida="mnopqrstuvxyzabcdefghil"
letras=frase.maketrans(entrada,salida)
print(frase.translate(letras))
import tkinter as tk
ventana=tk.Tk()
ventana.title("traductor")
ventana.geometry('200x300')
ventana.configure(background='white')
frase=tk.Entry(ventana)
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
root = tk.Button(ventana,text="Traducir:",bg="black",fg="white")
root.pack(padx=20,pady=10)
How can I "combine" these two codes (?
What you need to do is create a tk widget called label:
label = tk.Label(ventana, width=20)
label.pack()
Then you can simply make a function called translate and configure the text of the label however you want
def translate(phrase):
label.config(text=phrase)
lastly you should bind the function translate to the button so that when you press it the magic happens:)
Like this:
root = tk.Button(ventana,text="Traducir:",bg="black",fg="white", command=lambda: translate(phrase=frase.get()))
This is some ready to try code based on your question
import tkinter as tk
ventana=tk.Tk()
ventana.title("traductor")
ventana.geometry('200x300')
ventana.configure(background='white')
frase=tk.Entry(ventana)
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
label = tk.Label(ventana, width=20)
label.pack()
dic = {'Hello':'Bonjour'}
def translate(phrase):
if phrase in dic.keys():
text = dic[phrase]
else:
text='Cannot translate text'
label.config(text=text)
root = tk.Button(ventana,text="Traducir:",bg="black",fg="white", command=lambda: translate(phrase=frase.get()))
root.pack(padx=20,pady=10)
ventana.mainloop()
For the translation part the best you can do is create a dictionary. This way when someone enters a specific word in your EntryBox the program will be able to translate it:
You can do so like this:
dic = {'Good Morning':'Bonjour', 'Yes':'Oui'}
def translate(phrase):
if phrase in dic.keys():
text = dic[phrase]
else:
text='Cannot translate text'
label.config(text=text)
Last but not least, it's usually good to add a mainloop() call in the end of your program so as for the events happening in your app to be handled correctly. In your case you should add ventana.mainloop()
Please try this piece of code.
import tkinter as tk
def translate():
#==== Forget the position of the widgets in the window
for widget in ventana.winfo_children():
widget.pack_forget()
#=== Again place the entry box and the button
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
root.pack(padx=20,pady=10)
#==== Provide the text entered in the entry field
entrada="abcdefghilmnopqrstuvxyz"
salida="mnopqrstuvxyzabcdefghil"
letras=org_phrase.get().maketrans(entrada,salida)
#===print the translation (optional)
print(org_phrase.get().translate(letras))
#=== set it as label to display it
tk.Label(ventana,bg="white",text=org_phrase.get().translate(letras)).pack()
ventana=tk.Tk()
ventana.title("traductor")
ventana.geometry('200x300')
ventana.configure(background='white')
#=== Using stringvar to get the value
org_phrase=tk.StringVar()
#trans_phrase=tk.StringVar()
frase=tk.Entry(ventana,textvariable=org_phrase)
frase.pack(fill=tk.X,padx=5,pady=5,ipadx=5,ipady=5)
root =tk.Button(ventana,text="Traducir:",bg="black",fg="white",command=translate)
root.pack(padx=20,pady=10)
root.mainloop()
So, I'm making this game on python, Tkinter, where when I click the button "get a word", the computer randomly gives me a 6-8 letter word, now after it gives a word, an entry widget comes. In that, I have to type words and letters that are there inside the word given to me by the computer, so the problem is that after I am done typing the word or letter that I see in the word I should press the "enter" key and the computer should get to know about it and see the text written in the entry widget and check if the thing I wrote is there in the word given, if it is there, it should tell True.
else it should say false
can someone help me with this
thankyou
Try something like this:
import tkinter as tk
def print_entry(event):
print(variable.get())
root = tk.Tk()
variable = tk.StringVar(master=root)
entry = tk.Entry(root, textvariable=variable)
entry.pack()
# <Return> is the "Enter" key on your keyboard
entry.bind("<Return>", print_entry)
root.mainloop()
It binds to "<Return>" and executes print_entry. In print_entry it just prints everything inside the <tkinter.Entry>
I want to print the text of an Entry each time a new character is written.
By doing this with binding and a command to the widget the last character isn't printed.
I guess that the parameter 'textvariable' is getting updated after binding command had been executed. How to fix this?
from tkinter import *
master = Tk()
var = StringVar()
def execute_e(key):
print(var.get())
E = Entry(master, width=30, textvariable=var)
E.pack()
E.bind('<Key>', execute_e)
It's because the bound event function is being executed before the new key has been added.
Here's a simple workaround that uses the ability to add validation to an Entry widget (the validator accepts any key because it always returns True). The trick is that validator function is set-up to receive the value that the text will have if the change is allowed by specifying the %P when it's configuration as part of the Entry construction via the validatecommand=(validator_command, '%P').
Here's some documentation about adding validation to Entry widgets with details about how it works.
from tkinter import *
master = Tk()
var = StringVar()
def validator(new_value):
print(f'new_value: {new_value}')
return True
validator_command = master.register(validator)
E = Entry(master, width=30, textvariable=var,
validate='key',
validatecommand=(validator_command, '%P'))
E.pack()
master.mainloop()
I feel like this is a question of event handler. When a key is typed, your code first register a key press and execute the bound command execute_e. Only after it has processed this and your event handler has return will it update the entry with the character and proceed to update the tkinter variable.
Your print command therefore comes in before your variable have been updated and you print the previous version of your variable. If you try deleting a character from your entry, you'll see that you get the previous string with the character you have just erased.
The easiest way around that problem for you is probably to bind the command to the tkinter variable rather than the keybind. Do so using trace when the variable is writen like so :
var.trace('w', execute_e)
There are also some methods to manipulate the event handler and decide in which order to execute commands. root.after_idle will execute a command when the code has nothing else to do (when it has computed everything else you asked it to do). Try out this version of your code :
from tkinter import *
master = Tk()
var = StringVar()
def execute_e(*key):
def printy():
print(var.get())
master.after_idle(printy)
E = Entry(master, width=30, textvariable=var)
E.pack()
E.bind('<Key>', execute_e)
master.mainloop()
I wrote a python 3.4.2 programme to get a user input from python IDLE, perform some processing on the input and display a few statements in the python IDLE using print().
Now I am in the process of converting this to use a GUI using tkinter. This is the simple tkinter code I wrote for the GUI.
from tkinter import *
root=Tk()
root.title("Post-fix solver")
root.geometry("500x500")
mainframe=Frame(root)
mainframe.grid(column=0, row=0)
inputval=StringVar()
inputentry=Entry(mainframe,textvariable=inputval).grid(column=1,row=1)
executebutton=Button(mainframe,text="Run",command=check_expression).grid(column=1,row=5)
outputtext=Text(mainframe).grid(column=1,row=5)
root.mainloop()
So far I was able to get the user input through the Entry widget named inputentry in the GUI and send it to a variable in the original code using inputval.get(). Then it performs the processing on the input and shows the outputs of print() statement in the python IDLE.
My question is how can I modify the programme to send all those print() statements to the Text widget named outputtext and display them in the GUI?
I would be glad if you could show me how to do this without using classes as I am a beginner in python
3 easy steps:
1) Get the content of your variable and put it to a variable that I'm gonna name varContent;
2) Clear your text widget, that is, if the name of your text widget is text, then run text.delete(0, END);
3) Insert the string you've got in your variable varContent into your text text widget, that is, do text.insert(END, varContent).
I would do my code like this:
from tkinter import *
def check_expression():
#Your code that checks the expression
varContent = inputentry.get() # get what's written in the inputentry entry widget
outputtext.delete('0', 'end-1c') # clear the outputtext text widget
outputtext.insert(varContent)
root = Tk()
root.title("Post-fix solver")
root.geometry("500x500")
mainframe = Frame(root)
mainframe.grid(column=0, row=0)
inputentry = Entry(mainframe)
inputentry.grid(column=1, row=1)
executebutton = Button(mainframe, text="Run", command=check_expression)
executebutton.grid(column=1, row=5)
outputtext = Text(mainframe)
outputtext.grid(column=1, row=5)
root.mainloop()
For Python 3.x
After creating the entry box with inputentry=Entry(mainframe).grid() you can get the typed entries with inputentry.get().
Do the following to put the typed entry in a variable and to print it in the text widget named outputtext:
entryvar=inputentry.get() # the variable entryvar contains the text widget content
outputtext.delete(1.0,tk.END) # clear the outputtext text widget. 1.0 and tk.END are neccessary. tk implies the tkinter module. If you just want to add text dont incude that line
outputtext.insert(tk.END,entryvar) # insert the entry widget contents in the text widget. tk.END is necessary.
If you're using Python 3.4+ to run the program too, you can use the contextlib.redirect_stdout to capture the print output for a duration of a few statements into a file, or even a string:
import io
from contextlib import redirect_stdout
...
file = io.StringIO()
with redirect_stdout(file):
# here be all the commands whose print output
# we want to capture.
output = file.getvalue()
# output is a `str` whose contents is everything that was
# printed within the above with block.
Otherwise a better though a bit more arduous way is to make a StringIO file and print to it, so you'd have
buffer = io.StringIO()
print("something", file=buffer)
print("something more", file=buffer)
output = buffer.getvalue()
text.insert(END, output)
I need entry to contain only one file selection at a time. As it stands now, if the user hits button multiple times to select multiple files (say they selected the wrong file at first or they changed their mind), entry concatenates these multiple filenames all together. Basically, I want entry to contain only the user's last file selection.
Example Code:
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
def browse():
if entry.selection_present() == 1:
entry.selection_clear()
entry.insert(0, filedialog.askopenfilename(parent=frame))
root = Tk()
frame = ttk.Frame(root)
frame.pack()
entry = ttk.Entry(frame, width=100)
entry.pack()
button = ttk.Button(frame, text="Browse", command=browse)
button.pack()
root.mainloop()
Neither entry.selection_present() nor entry.selection_clear() do what I expect. entry.selection_present() always outputs 0, and entry.selection_clear() seems to do nothing.
I was able to get my code to work if I changed the if block to:
if entry.get() != "":
entry.delete(0,1000)
but this seems kind of hackish because the arguments - delete all characters up to 1000 - is arbitrary. What I really want is to clear the entire previous file selection.
Tkinter 8.5 documentation: https://www.tcl.tk/man/tcl8.5/TkCmd/ttk_entry.htm#M23
Use END (or 'end') to denote the end of the entry.
entry.delete(0, END)
Above statement will delete entry content. (from begining(0) to the end).
Alternatively, you can bind the entry with StringVar object, and later call set('') to clear the content.
v = StringVar()
entry = Entry(master, textvariable=v)
# to clear
v.set('')