【问题标题】:How to add placeholder to an Entry in tkinter?如何将占位符添加到 tkinter 中的条目?
【发布时间】:2021-12-20 03:12:16
【问题描述】:

我在 tkinter 中创建了一个登录窗口,其中有两个输入字段,第一个是用户名,第二个是密码。
代码

from tkinter import *

ui = Tk()

e1 = Entry(ui)
#i need a placeholder "Username" in the above entry field
e1.pack()

ui.mainloop()

我想在Entry 中添加一个名为“用户名”的占位符,但如果您在输入框内单击,文本应该会消失。

【问题讨论】:

标签: python user-interface tkinter


【解决方案1】:

您需要为此条目设置默认值。像这样:

from tkinter import *

ui = Tk()

e1 = Entry(ui)
e1.insert(0, 'username')
e1.pack()

ui.mainloop()

那么如果你想在点击条目时删除内容,那么你必须绑定一个鼠标点击事件和一个事件处理方法来更新这个条目的内容。 这是给你的link

【讨论】:

  • 您应该绑定到<FocusIn>,而不是绑定到单击,因为可以通过键盘将焦点切换到条目小部件。如果你真的展示了如何做到这一点,你的答案会好一点。
  • 根据 Bryan 的建议,为未来的读者准备了一个简单的衬线:e1.bind("<FocusIn>", lambda args: e1.delete('0', 'end'))
  • @Nae 请你为 lambda args 解释一下: 我想更好地理解
  • @ADWAN bind 默认将event 值传递给其回调按钮,这就是args 的原因。我使用lambda的原因是我想将一些值传递给实际的方法,delete,我想使用。
【解决方案2】:

您可以创建一个继承自Entry 的类,如下所示:

import tkinter as tk

class EntryWithPlaceholder(tk.Entry):
    def __init__(self, master=None, placeholder="PLACEHOLDER", color='grey'):
        super().__init__(master)

        self.placeholder = placeholder
        self.placeholder_color = color
        self.default_fg_color = self['fg']

        self.bind("<FocusIn>", self.foc_in)
        self.bind("<FocusOut>", self.foc_out)

        self.put_placeholder()

    def put_placeholder(self):
        self.insert(0, self.placeholder)
        self['fg'] = self.placeholder_color

    def foc_in(self, *args):
        if self['fg'] == self.placeholder_color:
            self.delete('0', 'end')
            self['fg'] = self.default_fg_color

    def foc_out(self, *args):
        if not self.get():
            self.put_placeholder()

if __name__ == "__main__": 
    root = tk.Tk() 
    username = EntryWithPlaceholder(root, "username")
    password = EntryWithPlaceholder(root, "password", 'blue')
    username.pack()
    password.pack()  
    root.mainloop()

【讨论】:

  • 这可以通过定义一个与 bindtags 一起使用的自定义类标签 bind_class 来进一步改进。
  • 另外,在__init__ 上接受*args**kwargs 可能是明智的,尽管您可能需要处理FocusInFocusOut 事件中的textvariable 关键字防止占位符被发送到StringVar
【解决方案3】:
from tkinter import *

root=Tk()
root.geometry("300x200+600+250")
root.config(background="#E0FFFF")
root.resizable(False,False)


def userText(event):
    e1.delete(0,END)
    usercheck=True

def passText(event):
    e2.delete(0, END)
    passcheck=True



a=StringVar()
b=StringVar()
usercheck=False
passcheck=False


Label(root,text="User name",bg="#E0FFFF").place(x=20,y=50)
e1= Entry(root,textvariable=a)
e1.place(x=100,y=50)
e1.insert(0,"Enter username")
e1.bind("<Button>",userText)


Label(root,text="Password",bg="#E0FFFF").place(x=20,y=95)
e2= Entry(root,textvariable=b)
e2.place(x=100,y=95)
e2.insert(0,"Enter password")
e2.bind("<Button>",passText)


root.mainloop()

【讨论】:

    【解决方案4】:

    这适用于您想要的任何占位符。

    from tkinter import *
    root = Tk()
    
    my_entry = Entry(root, width=50)
    my_entry.pack()
    my_entry.insert(0, "Place Holder")
    my_entry.configure(state=DISABLED)
    
    def on_click(event):
        my_entry.configure(state=NORMAL)
        my_entry.delete(0, END)
    
        # make the callback only work once
        my_entry.unbind('<Button-1>', on_click_id)
    
    on_click_id = my_entry.bind('<Button-1>', on_click)
    
    root.mainloop()
    

    更新(改进)

    • 不鼓励使用import *,因此,我们应该像这样导入import tkinter as tk
    • 现在我们使用on_focus_out 函数在文本字段为空时重新插入占位符(如果您不希望发生这种情况,可以使用旧代码中的方法)
    • 我创建了两个 Entry 小部件来描述更改。
    import tkinter as tk
    
    
    def on_focus_in(entry):
        if entry.cget('state') == 'disabled':
            entry.configure(state='normal')
            entry.delete(0, 'end')
    
    
    def on_focus_out(entry, placeholder):
        if entry.get() == "":
            entry.insert(0, placeholder)
            entry.configure(state='disabled')
    
    
    root = tk.Tk()
    
    entry_x = tk.Entry(root, width=50)
    entry_x.pack(pady=10)
    entry_x.insert(0, "Place Holder X")
    entry_x.configure(state='disabled')
    
    entry_y = tk.Entry(root, width=50)
    entry_y.pack(pady=10)
    entry_y.insert(0, "Place Holder Y")
    entry_y.configure(state='disabled')
    
    x_focus_in = entry_x.bind('<Button-1>', lambda x: on_focus_in(entry_x))
    x_focus_out = entry_x.bind(
        '<FocusOut>', lambda x: on_focus_out(entry_x, 'Place Holder X'))
    
    y_focus_in = entry_y.bind('<Button-1>', lambda x: on_focus_in(entry_y))
    y_focus_out = entry_y.bind(
        '<FocusOut>', lambda x: on_focus_out(entry_y, 'Place Holder Y'))
    
    root.mainloop()
    
    

    【讨论】:

      【解决方案5】:

      一个工作占位符类。它的作用是绑定到&lt;FocusIn&gt;&lt;FocusOut&gt;,这样当您将焦点放在它上面时,如果没有文本,它会将您的placeholder 插入其中。你也可以改变颜色,如果它被选中。

      class Placeholder:
          def __init__(self,master,placeholder='',placeholdercolor='grey',color='black',**kwargs):
              self.e = Entry(master,fg=placeholdercolor,**kwargs)
              self.e.bind('<FocusIn>',self.focus_in)
              self.e.bind('<FocusOut>',self.focus_out)
              self.e.insert(0, placeholder)
              self.placeholder = placeholder
              self.placeholdercolor=placeholdercolor
              self.color = color
      
          def pack(self,side=None,**kwargs):
              self.e.pack(side=side,**kwargs)
      
          def place(self,side=None,**kwargs):
              self.e.place(side=side,**kwargs)
      
          def grid(self,column=None,**kwargs):
              self.e.grid(column=column,**kwargs)
      
          def focus_in(self,e):
              if self.e.get() == self.placeholder:
                  self.e.delete(0,END)
              self.e.configure(fg=self.color)
      
          def focus_out(self,e):
              if self.e.get() == '':
                  self.e.configure(fg=self.placeholdercolor)
                  self.e.delete(0,END)
                  self.e.insert(0,self.placeholder)
      

      【讨论】:

        【解决方案6】:

        对于比上面列出的更紧凑的解决方案,我建议您创建一个函数来擦除点击事件 (lambda) 上的文本框,如下所示。

        from tkinter import *   
        
        def clear_entry(event, entry):
            entry.delete(0, END)
            entry.unbind('<Button-1>', click_event)
        
        ui = Tk()
        
        entry = Entry(ui)
        
        entry.pack()
        placeholder_text = '<enter-placeholder>'
        entry.insert(0, placeholder_text)
        
        entry.bind("<Button-1>", lambda event: clear_entry(event, entry))
        
        ui.mainloop()
        
        

        &lt;Button-1&gt;”代表当你左键点击输入框,所以不要改变它,一旦你点击输入框就会触发事件并运行函数clear_entry。在定义placeholder_text 和使用entry.insert 之前,您必须声明函数和entry 元素。希望这是解决此问题的可行方法。

        【讨论】:

          【解决方案7】:

          我的解决方案是将tk.Entry 子类化并控制内容和颜色,将&lt;FocusIn&gt;&lt;FocusOut&gt; 事件绑定到根据需要填充和清除文本的方法。这是行为:

          这里是完整的示例代码:

          import tkinter as tk
          
          class PlaceholderEntry(tk.Entry):
              def __init__(self, master=None, placeholder='', cnf={}, fg='black',
                           fg_placeholder='grey50', *args, **kw):
                  super().__init__(master=None, cnf={}, bg='white', *args, **kw)
                  self.fg = fg
                  self.fg_placeholder = fg_placeholder
                  self.placeholder = placeholder
                  self.bind('<FocusOut>', lambda event: self.fill_placeholder())
                  self.bind('<FocusIn>', lambda event: self.clear_box())
                  self.fill_placeholder()
          
              def clear_box(self):
                  if not self.get() and super().get():
                      self.config(fg=self.fg)
                      self.delete(0, tk.END)
          
              def fill_placeholder(self):
                  if not super().get():
                      self.config(fg=self.fg_placeholder)
                      self.insert(0, self.placeholder)
              
              def get(self):
                  content = super().get()
                  if content == self.placeholder:
                      return ''
                  return content
          
          class App(tk.Frame):
              def __init__(self, master=None):
                  self.root = master
                  super().__init__(master, borderwidth=0, relief=tk.RAISED)
                  
                  self.root.title('Placeholder example')
                  self.pack_propagate(False)
                  self.pack()
                  
                  self.entry = PlaceholderEntry(self.root, placeholder='This text is a placeholder')
                  self.entry.pack()
                  
                  self.btn = tk.Button(self.root, text='Nothing', highlightcolor='cyan')
                  self.btn.pack()
                  
          
          root = tk.Tk()
          app = App(master=root)
          
          app.root.mainloop()
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-08-22
            • 2021-03-16
            • 1970-01-01
            • 1970-01-01
            • 2021-01-31
            • 2018-11-27
            相关资源
            最近更新 更多