如何将占位符添加到 tkinter 中的条目?
How to add placeholder to an Entry in tkinter?
我在 tkinter 中创建了一个登录名 window,它有两个输入字段,第一个是用户名,第二个是密码。
代码
from tkinter import *
ui = Tk()
e1 = Entry(ui)
#i need a placeholder "Username" in the above entry field
e1.pack()
ui.mainloop()
我想要在 Entry
中使用一个名为“用户名”的占位符,但如果您在输入框内单击,文本应该会消失。
您需要为此条目设置一个默认值。像这样:
from tkinter import *
ui = Tk()
e1 = Entry(ui)
e1.insert(0, 'username')
e1.pack()
ui.mainloop()
那么如果你想在点击条目时删除内容,那么你必须绑定一个鼠标点击事件和一个事件处理方法来更新这个条目的内容。
这是给你的 link。
您可以创建一个继承自 Entry
的 class,如下所示:
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()
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()
这适用于您想要的任何占位符。
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()
一个工作占位符class。它的作用是绑定到 <FocusIn>
和 <FocusOut>
,这样当您将焦点放在它上面时,如果没有文本,它会将您的 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)
为了获得比上面列出的更紧凑的解决方案,我建议您创建一个函数来清除单击事件 (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()
“<Button-1>
”代表左键点击输入框,所以不要改变它,一旦你点击输入框,它就会触发事件和 运行 函数 clear_entry
。您必须在定义 placeholder_text
和使用 entry.insert
之前声明函数和 entry
元素。希望这是解决此问题的可行方法。
我的解决方案是继承 tk.Entry
并控制内容和颜色,将 <FocusIn>
和 <FocusOut>
事件绑定到根据需要填充和清除文本的方法。这是行为:
这里是完整的示例代码:
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()
我在 tkinter 中创建了一个登录名 window,它有两个输入字段,第一个是用户名,第二个是密码。
代码
from tkinter import *
ui = Tk()
e1 = Entry(ui)
#i need a placeholder "Username" in the above entry field
e1.pack()
ui.mainloop()
我想要在 Entry
中使用一个名为“用户名”的占位符,但如果您在输入框内单击,文本应该会消失。
您需要为此条目设置一个默认值。像这样:
from tkinter import *
ui = Tk()
e1 = Entry(ui)
e1.insert(0, 'username')
e1.pack()
ui.mainloop()
那么如果你想在点击条目时删除内容,那么你必须绑定一个鼠标点击事件和一个事件处理方法来更新这个条目的内容。 这是给你的 link。
您可以创建一个继承自 Entry
的 class,如下所示:
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()
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()
这适用于您想要的任何占位符。
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()
一个工作占位符class。它的作用是绑定到 <FocusIn>
和 <FocusOut>
,这样当您将焦点放在它上面时,如果没有文本,它会将您的 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)
为了获得比上面列出的更紧凑的解决方案,我建议您创建一个函数来清除单击事件 (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()
“<Button-1>
”代表左键点击输入框,所以不要改变它,一旦你点击输入框,它就会触发事件和 运行 函数 clear_entry
。您必须在定义 placeholder_text
和使用 entry.insert
之前声明函数和 entry
元素。希望这是解决此问题的可行方法。
我的解决方案是继承 tk.Entry
并控制内容和颜色,将 <FocusIn>
和 <FocusOut>
事件绑定到根据需要填充和清除文本的方法。这是行为:
这里是完整的示例代码:
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()