I know this Q has been answered in this site, but im looking for a more simpler answer, and ive seen one before but then the question has been deleted or something, I cant find
I'm not really clear on what you're asking, so I'm guessing you're asking how to know when the entry widget has placeholder text and when it doesn't so that you know when to clear it and when not to clear it.
The easiest solution is to add an attribute to the entry with the replacement text, and then compare it to the contents before deleting.
First, let's create a function to initialize the placeholder text for a widget. This function does a few simple things: it adds a placeholder
attribute on the widget, and it establishes the bindings. It also inserts the placeholder if the widget is empty:
def init_placeholder(widget, placeholder_text):
widget.placeholder = placeholder_text
if widget.get() == "":
widget.insert("end", placeholder_text)
# set up a binding to remove placeholder text
widget.bind("", remove_placeholder)
widget.bind("", add_placeholder)
Now let's tweak your remove
function to be a bit more generic. Since it's called via an event, it can use event.widget
rather than a hard-coded reference to a specific widget. It also uses the placeholder
attribute which we added to the widget. These two techniques lets it be used by more than one widget.
def remove_placeholder(event):
placeholder_text = getattr(event.widget, "placeholder", "")
if placeholder_text and event.widget.get() == placeholder_text:
event.widget.delete(0, "end")
Finally we need to implement the add_placeholder
function. This function will add the placeholder when the widget loses focus and the user hasn't typed anything. It needs to check if the entry widget has a placeholder, and if it does and the widget is empty, it adds the placeholder. Like remove_placeholder
it uses event.widget
and the placeholder
attribute:
def add_placeholder(event):
placeholder_text = getattr(event.widget, "placeholder", "")
if placeholder_text and event.widget.get() == "":
event.widget.insert(0, placeholder_text)
I've modified your program to use different placeholder text for each of the two entry widgets to show that the functions are generic and not tied to a specific entry widget.
from tkinter import *
root = Tk()
def remove_placeholder(event):
"""Remove placeholder text, if present"""
placeholder_text = getattr(event.widget, "placeholder", "")
if placeholder_text and event.widget.get() == placeholder_text:
event.widget.delete(0, "end")
def add_placeholder(event):
"""Add placeholder text if the widget is empty"""
placeholder_text = getattr(event.widget, "placeholder", "")
if placeholder_text and event.widget.get() == "":
event.widget.insert(0, placeholder_text)
def init_placeholder(widget, placeholder_text):
widget.placeholder = placeholder_text
if widget.get() == "":
widget.insert("end", placeholder_text)
# set up a binding to remove placeholder text
widget.bind("", remove_placeholder)
widget.bind("", add_placeholder)
e = Entry(root)
e.pack(padx=100,pady=(30,0))
e2 = Entry(root)
e2.pack( pady=(20,100))
init_placeholder(e, "First Name")
init_placeholder(e2, "Last Name")
root.mainloop()
Arguably, a better way to implement this would be to create a custom class. That way everything is encapsulated in one place. Here's an example:
class EntryWithPlaceholder(Entry):
def __init__(self, *args, **kwargs):
self.placeholder = kwargs.pop("placeholder", "")
super().__init__(*args, **kwargs)
self.insert("end", self.placeholder)
self.bind("", self.remove_placeholder)
self.bind("", self.add_placeholder)
def remove_placeholder(self, event):
"""Remove placeholder text, if present"""
if self.get() == self.placeholder:
self.delete(0, "end")
def add_placeholder(self,event):
"""Add placeholder text if the widget is empty"""
if self.placeholder and self.get() == "":
self.insert(0, self.placeholder)
You can use this class just like an Entry
widget, but you can specify a placeholder:
e3 = EntryWithPlaceholder(root, placeholder="Address")
e3.pack()