Adding placeholders to tkinter Entry widget in a procedural way

后端 未结 4 1266
独厮守ぢ
独厮守ぢ 2021-01-25 13:20

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

4条回答
  •  生来不讨喜
    2021-01-25 14:03

    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.

    Using functions

    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()
    

    Using a custom class

    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()
    

提交回复
热议问题