0

Can you help me to display a text in my entry, which disappears after clicking on the entry?

For this I have the following example in the entry with the text "Search". I would like to have exactly this text displayed in my entry.

Thanks a lot!

enter image description here

enter image description here

acw1668
  • 40,144
  • 5
  • 22
  • 34
Djangopy
  • 31
  • 6
  • You should read this [ask] and note that there are many questions here about [tag:tkinter-entry]. I'm sure after a little research you will be able to solve this for yourself. – Thingamabobs Oct 24 '20 at 16:23
  • Does this answer your question? [How to set default text for a Tkinter Entry widget](https://stackoverflow.com/questions/20125967/how-to-set-default-text-for-a-tkinter-entry-widget) – Thingamabobs Oct 24 '20 at 16:26
  • Added an answer, would appreciate marking as the correct answer – Delrius Euphoria Nov 05 '20 at 04:21

1 Answers1

1

What your looking for is called placeholders. Unfortunately there is no default option with tkinter on placeholders, but a simple placeholder would look like:

import tkinter as tk

root = tk.Tk()

placeholder = 'Your text here'

def erase(event=None):
    if e.get() == placeholder:
        e.delete(0,'end')
def add(event=None):
    if e.get() == '':
        e.insert(0,placeholder)

e = tk.Entry(root)
e.pack(padx=10,pady=10)

dummy = tk.Entry(root) #dummy widget just to see other widget lose focus
dummy.pack(padx=10,pady=10)

add()
e.bind('<FocusIn>',erase)
e.bind('<FocusOut>',add)

root.mainloop()

But this code has many downfalls as the entry methods wont work properly if your looking to manipulate with more data, so what I prefer to do is to make a class and use it, instead of using the default Entry class.

This is a code that I had made to work for similar situations, I dont make any claim that this is any how perfect, but this could get your job done.

import tkinter as tk
from tkinter import ttk as ttk

class PlaceholderEntry(ttk.Entry):
    '''
    Custom modern Placeholder Entry box, takes positional argument master and placeholder along with\n
    textcolor(default being black) and placeholdercolor(default being grey).\n
    Use acquire() for getting output from entry widget\n
    Use shove() for inserting into entry widget\n
    Use remove() for deleting from entry widget\n
    Use length() for getting the length of text in the widget\n
    BUG 1: Possible bugs with binding to this class\n
    BUG 2: Anomalous behaviour with config or configure method
    '''
    def __init__(self, master, placeholder,textcolor='black',placeholdercolor='grey', **kwargs):
        self.text = placeholder
        self.__has_placeholder = False # placeholder flag
        self.placeholdercolor = placeholdercolor
        self.textcolor = textcolor

        # style for ttk widget
        self.s = ttk.Style()

        # init entry box
        ttk.Entry.__init__(self, master, style='my.TEntry', **kwargs)
        self.s.configure('my.TEntry',forground=self.placeholdercolor)

        # add placeholder if box empty
        self._add()

        # bindings of the widget
        self.bind('<FocusIn>', self._clear)
        self.bind('<FocusOut>', self._add)
        self.bind_all('<Key>', self._normal)
        self.bind_all('<Button-1>', self._cursor)

    def _clear(self, *args): # method to remove the placeholder
        if self.get() == self.text and self.__has_placeholder:  # remove placeholder when focus gain
            self.delete(0, tk.END)
            self.s.configure('my.TEntry', foreground='black',
                             font=(0, 0, 'normal'))
            self.__has_placeholder = False #set flag to false

    def _add(self, *args): # method to add placeholder
        if self.get() == '' and not self.__has_placeholder:  # if no text add placeholder
            self.s.configure('my.TEntry', foreground=self.placeholdercolor,
                             font=(0, 0, 'bold'))
            self.insert(0, self.text)  # insert placeholder
            self.icursor(0)  # move insertion cursor to start of entrybox
            self.__has_placeholder = True #set flag to true

    def _normal(self, *args): #method to set the text to normal properties
        self._add()  # if empty add placeholder
        if self.get() == self.text and self.__has_placeholder:  # clear the placeholder if starts typing
            self.bind('<Key>', self._clear)
            self.icursor(-1)  # keep insertion cursor to the end
        else:
            self.s.configure('my.TEntry', foreground=self.textcolor,
                         font=(0, 0, 'normal'))  # set normal font

    def acquire(self):  
        """Custom method to get the text"""
        if self.get() == self.text and self.__has_placeholder:
            return 'None'
        else:
            return self.get()

    def shove(self, index, string):  
        """Custom method to insert text into entry"""
        self._clear()
        self.insert(index, string)

    def remove(self, first, last):  
        """Custom method to remove text from entry"""
        if self.get() != self.text:
            self.delete(first, last)
            self._add()
        elif self.acquire() == self.text and not self.__has_placeholder:
            self.delete(first, last)
            self._add()

    def length(self):
        """Custom method to get the length of text in the entry widget"""
        if self.get() == self.text and self.__has_placeholder:
            return 0
        else:
            return len(self.get())

    def _cursor(self, *args):  # method to not allow user to move cursor when placeholder exists
        if self.get() == self.text and self.__has_placeholder:
            self.icursor(0)

#usage
if __name__ == '__main__':
    root = tk.Tk()
    
    e = PlaceholderEntry(root,placeholder='Your text')
    e.pack(padx=10,pady=10)
    
    dummy = tk.Entry(root) #dummy widget just to see other widget lose focus
    dummy.pack(padx=10,pady=10)
    
    root.mainloop()

Though I recommend you use the latter example once you understand whats going on behind the hood.

PS:- The example with class is faulty when making more than one instance of the class.

Delrius Euphoria
  • 14,910
  • 3
  • 15
  • 46