I am trying to make a program that will return the user's input and also clear the Entry when Return/Enter is pressed. When ran, the second method (def e_delete(e):) always gives the error, AttributeError: Event instance has no attribute 'delete' and if the e is changed to self no string is returned and no error happens.
from Tkinter import *
import os.path
import PIL.Image, PIL.ImageTk
import Tkinter as tk
def on_change(e):
inp = e.widget.get()
print inp
root = tk.Tk()
#Makes a canvas for objects
canvas = Canvas(root, height=100, width=400)
#Displays the canvas
canvas.grid(row=3, column=2)
root.grid_columnconfigure(0, weight=1)
root.grid_columnconfigure(1, weight=1)
label = Label(root, text="Enter an element or the atomic number from 1 to 118.").grid(row=0, column=2)
e = tk.Entry(root)
e.pack()
e.bind("<Return>", on_change)
e.grid(row=2, column=2)
e.focus()
def e_delete(e):
e.delete(0, 'end')
e.bind("<Return>", e_delete)
#img = create_image(0, 300, 'ptable.png')
root.mainloop()
You're doing this:
def entry_delete(e):
e.delete(0, 'end')
The value that gets passed to a callback for an event binding is an Event object. And they don't have a delete method.
The fact that you also have a global variable with the same name doesn't make any difference (except to confuse you and other readers); the parameter e hides the global e.
So, if you want to call a method on your Entry object, don't hide it:
def e_delete(evt):
e.delete(0, 'end')
Or, if you want to call a method on whatever widget triggered the event (which, in this case, will always be the same thing, so it's just a matter of which one makes more sense to you), you can do that instead:
def e_delete(evt):
evt.widget.delete(0, 'end')
However, it's usually even better to give everything clear and distinct names to avoid this kind of confusion:
entry = tk.Entry(root)
ent.pack()
entry.bind("<Return>", on_change)
entry.grid(row=2, column=2)
entry.focus()0
def entry_delete(evt):
entry.delete(0, 'end')
entry.bind("<Return>", entry_delete)
Related
def entering(a):
value=entry1.get() #entry1.get()is used to get values which entered in entry box
label1=Label(root, text =value, height=10)
label1.pack()
entry1.delete(0, END) # used to clear entry box
root.bind('<Return>',entering)
how do I remove the widget that I created in the function call entering?
I know about the destroy function. I don't want to destroy it after a particular time.
I want to destroy it or overwrite it into the widget when I call the function again
I think this is what you expect:
import tkinter as tk
root = tk.Tk()
myentry = tk.Entry(root)
myentry.pack()
var = tk.StringVar(root)
mylabel = tk.Label(root, textvariable= var)
mylabel.pack()
def entering(event):
text = myentry.get()
var.set(text)
myentry.bind('<Return>', entering)
root.mainloop()
from tkinter import *
def hi(event):
print(txt.get('1.0',END))
txt.delete('1.0',END)
root = Tk()
lbl = Label(root, text="client")
lbl.pack()
txt = Text(root, height=10, width=50)
txt.pack()
txt.bind('<Return>', hi)
btn = Button(root, text="OK")
btn.pack()
root.mainloop()
When I delete Text widget contents, a blank line is left. How to prevent that?
The built-in bindings cause a newline to be inserted when you press the return key. When you create a binding, your bound function is called before the default behavior. Thus, when you press return, your function deletes everything, and then the default action inserts a newline.
If you want to prevent the default action from happening, your function needs to return the string break:
def hi(event):
print(txt.get('1.0',END))
txt.delete('1.0',END)
return "break"
What happens is that the text widget still gets the return you entered. Binding the Enter does not inhibits the propagation of the event after your function ends, unless you alter it to cancel event propagation by returning the break string, like this:
def hi(event):
print(txt.get('1.0',END))
txt.delete('1.0',END)
return 'break'
You must ask tkinter not to propagate that event to other handlers as follows:
from tkinter import *
def hi(event):
print(txt.get('1.0',END))
txt.delete('1.0',END)
return "break"
root = Tk()
lbl = Label(root, text="client")
lbl.pack()
txt = Text(root, height=10, width=50)
txt.pack()
txt.bind('<Return>', hi)
btn = Button(root, text="OK")
btn.pack()
root.mainloop()
I got example code were there are two windows and in the second one there's a tick box that doesn't change value when it is ticked. How can I fix this? I tried returning the value of the tickbox however that failed as well.
from tkinter import *
root = Tk()
def open_custom_gui():
custom_gui()
b = Button(root,command=open_custom_gui)
b.grid(row=1,column=0)
def custom_gui():
def getinfo():
print(var1.get())
custom= Tk()
var1 = IntVar()
tickbox_1 = Checkbutton(custom,text='TEST',variable=var1,)
tickbox_1.grid(row=0,column=0)
b = Button(custom,command=getinfo)
b.grid(row=1,column=0)
custom.mainloop()
root.mainloop()
The problem has something to do with calling Tk() twice. You can fix that by explicitly creating a second Toplevel window.
from tkinter import *
root = Tk()
def open_custom_gui():
custom_gui()
b = Button(root, command=open_custom_gui)
b.grid(row=1, column=0)
def custom_gui():
def getinfo():
print(var1.get())
custom = Toplevel() # CHANGE THIS (don't call Tk() again)
var1 = IntVar()
tickbox_1 = Checkbutton(custom, text='TEST', variable=var1)
tickbox_1.grid(row=0, column=0)
b = Button(custom, command=getinfo)
b.grid(row=1, column=0)
custom.mainloop()
root.mainloop()
Alternatively you can also fix it by specifying the second Tk instance when you create the IntVar tkinter variable:
def custom_gui():
def getinfo():
print(var1.get())
custom = Tk()
var1 = IntVar(master=custom) # ADD a "master" keyword argument
tickbox_1 = Checkbutton(custom, text='TEST', variable=var1)
tickbox_1.grid(row=0, column=0)
b = Button(custom, command=getinfo)
b.grid(row=1, column=0)
custom.mainloop()
However I would suggest using the first approach because the documentation says the following (about adding the argument to the IntVar constructor):
The constructor argument is only relevant if you’re running Tkinter with
multiple Tk instances (which you shouldn’t do, unless you really know what
you’re doing).
I am trying to make a simple GUI calculator just for addition/subtraction in the beginning. I am able to print the result to the console but I want to print it to the Entry box like the First Name entry box for example but not able to do it. I would really appreciate if you could help.(*Please neglect the alignment right now of the buttons I am focusing on the functioning, trying to get it right)
from Tkinter import *
import tkMessageBox
import sys
class scanner:
list1 = []
def __init__(self,parent):
self.entrytext = StringVar()
self.entrytext1 = StringVar()
Label(root, text="first name", width=10).grid(row=0,column=0)
Entry(root, textvariable=self.entrytext, width=10).grid(row=0,column=1)
Label(root, text="last name", width=10).grid(row=1,column=0)
Entry(root, textvariable=self.entrytext1, width=10).grid(row=1,column=1)
Button(root, text="ADD", command=self.add).grid()
Button(root, text="SUBTRACT", command=self.subtract).grid()
def add(self):
global a
global b
self.a=int(self.entrytext.get())
self.b=int(self.entrytext1.get())
print "result is", self.a+self.b
def subtract(self):
global a
global b
self.a=int(self.entrytext.get())
self.b=int(self.entrytext1.get())
print "result is", self.a-self.b
root= Tk()
root.geometry("300x300")
calc = scanner(root)
root.mainloop()
If you want to show the result of the operation as a label's text, just create a new label and configure it with the text option and the string you are printing as its value. As a side note, you don't need the global statements, and the use of instance variables is not necessary either. However, it is very important to check that the content of the entries are actually valid numbers:
def __init__(self,parent):
# ...
self.result = Label(root, text='')
self.result.grid(row=4, column=0)
def add(self):
try:
a = int(self.entrytext.get())
b = int(self.entrytext1.get())
self.result.config(text=str(a+b))
except ValueError:
print("Incorrect values")
To add entry text to the widget, use the insert method. To replace the current text, you can call delete before you insert the new text.
e = Entry(master)
e.pack()
e.delete(0, END)
e.insert(0, "a default value")
The first parameter in the delete method is which number character to delete from and the second parameter is where to delete too. Notice how END is a tkinter variable.
The parameters for the insert function is where the text will be inserted too, and the second parameter is what will be inserted.
In the future, I recommend going to Effbot and reading about the widget that you are trying to use to find out all about it.
I'm trying to use an Entry field to get manual input, and then work with that data.
All sources I've found claim I should use the get() function, but I haven't found a simple working mini example yet, and I can't get it to work.
I hope someone can tel me what I'm doing wrong. Here's a mini file:
from tkinter import *
master = Tk()
Label(master, text="Input: ").grid(row=0, sticky=W)
entry = Entry(master)
entry.grid(row=0, column=1)
content = entry.get()
print(content) # does not work
mainloop()
This gives me an Entry field I can type in, but I can't do anything with the data once it's typed in.
I suspect my code doesn't work because initially, entry is empty. But then how do I access input data once it has been typed in?
It looks like you may be confused as to when commands are run. In your example, you are calling the get method before the GUI has a chance to be displayed on the screen (which happens after you call mainloop.
Try adding a button that calls the get method. This is much easier if you write your application as a class. For example:
import tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.entry = tk.Entry(self)
self.button = tk.Button(self, text="Get", command=self.on_button)
self.button.pack()
self.entry.pack()
def on_button(self):
print(self.entry.get())
app = SampleApp()
app.mainloop()
Run the program, type into the entry widget, then click on the button.
You could also use a StringVar variable, even if it's not strictly necessary:
v = StringVar()
e = Entry(master, textvariable=v)
e.pack()
v.set("a default value")
s = v.get()
For more information, see this page on effbot.org.
A simple example without classes:
from tkinter import *
master = Tk()
# Create this method before you create the entry
def return_entry(en):
"""Gets and prints the content of the entry"""
content = entry.get()
print(content)
Label(master, text="Input: ").grid(row=0, sticky=W)
entry = Entry(master)
entry.grid(row=0, column=1)
# Connect the entry with the return button
entry.bind('<Return>', return_entry)
mainloop()
*
master = Tk()
entryb1 = StringVar
Label(master, text="Input: ").grid(row=0, sticky=W)
Entry(master, textvariable=entryb1).grid(row=1, column=1)
b1 = Button(master, text="continue", command=print_content)
b1.grid(row=2, column=1)
def print_content():
global entryb1
content = entryb1.get()
print(content)
master.mainloop()
What you did wrong was not put it inside a Define function then you hadn't used the .get function with the textvariable you had set.
you need to put a textvariable in it, so you can use set() and get() method :
var=StringVar()
x= Entry (root,textvariable=var)
Most of the answers I found only showed how to do it with tkinter as tk. This was a problem for me as my program was 300 lines long with tons of other labels and buttons, and I would have had to change a lot of it.
Here's a way to do it without importing tkinter as tk or using StringVars. I modified the original mini program by:
making it a class
adding a button and an extra method.
This program opens up a tkinter window with an entry box and an "Enter" button. Clicking the Enter button prints whatever is in the entry box.
from tkinter import *
class mini():
def __init__(self):
master = Tk()
Label(master, text="Input: ").grid(row=0, sticky=W)
Button(master, text='Enter', command=self.get_content).grid(row=1)
self.entry = Entry(master)
self.entry.grid(row=0, column=1)
master.mainloop()
def get_content(self):
content = self.entry.get()
print(content)
m = mini()