以程序方式向 tkinter Entry 小部件添加占位符 [英] Adding placeholders to tkinter Entry widget in a procedural way

查看:64
本文介绍了以程序方式向 tkinter Entry 小部件添加占位符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题已经在这个网站上得到了回答,但我正在寻找一个更简单的答案,我以前看过一个,但后来这个问题被删除了或者其他什么,我找不到它.希望有人有更好、更简单的方法来解决它.与 class 相关的东西可能会更好,因为我可以轻松地将它与更多 Entry 小部件

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 it. Hopefully someone is having a better and easier way around to it. Something related to class might be better as I could use it easily with more Entry widgets

这是一个片段:

from tkinter import *

root = Tk()

def remove(event):
    e.delete(0, END)

e = Entry(root)
e.insert(0, 'PLACEHOLDER')
e.pack(padx=100,pady=(30,0))
e.bind('<FocusIn>', remove)

e2 = Entry(root)
e2.pack( pady=(20,100))

root.mainloop()

是的,一旦它失去焦点并再次获得焦点,这将删除框内的所有其他项目,包括我们最初输入的文本.无论如何,要解决这个问题并使用 tkinter 拥有一个完美的占位符,我知道没有内置的方法.

Yes, this will remove all the other items inside of the box once it looses focus and gains it again, including the text we enter at first. Anyway to get around that and have a perfect placeholder with tkinter, I'm aware there is no inbuilt way.

提前致谢:D

推荐答案

这是一个非常简单的例子.在此示例中,我们包含了一些功能/注意事项:

Here is a very simple example. In this example we include a couple of features/caveats:

  • 占位符的幻影文本
  • entry.input 将返回 None 如果它的文本是占位符或为空
  • entry.input 应该用来代替 .get().insert()..input 逻辑旨在为您提供此类小部件的正确结果..get() 不够智能,无法返回正确的数据,并且 .insert() 已重新配置为 .input
  • 在您键入时占位符被杂耍
  • 占位符可以用 .insert() 覆盖 ~ 无需使用 .delete().你仍然应该使用 entry.input 代替
  • ghost text for the placeholder
  • entry.input will return None if it's text is the placeholder or empty
  • entry.input should be used in place of .get() and .insert(). The .input logic is designed to give you the proper results for this type of widget. .get() is not smart enough to return the proper data, and .insert() has been reconfigured as a proxy to .input
  • placeholder is juggled while you type
  • placeholder can be overwritten with .insert() ~ no need to use .delete(). You should still use entry.input instead
#widgets.py

import tkinter as tk

class PlaceholderEntry(tk.Entry):
    '''
        All Of These Properties Are For Convenience
    '''
    @property
    def input(self):
        return self.get() if self.get() not in [self.__ph, ''] else None
        
    @input.setter
    def input(self, value):
        self.delete(0, 'end')
        self.insert(0, value)
        self.configure(fg = self.ghost if value == self.__ph else self.normal)
    
    @property
    def isempty(self) -> bool:
        return self.get() == ''
    
    @property     
    def isholder(self) -> bool:
        return self.get() == self.__ph
        
    def __init__(self, master, placeholder, **kwargs):
        tk.Entry.__init__(self, master, **{'disabledforeground':'#BBBBBB', **kwargs})
        
        self.normal = self['foreground']
        self.ghost  = self['disabledforeground']
        
        self.__ph = placeholder
        self.input = placeholder
        
        vcmd = self.register(self.validate)
        self.configure(validate='all', validatecommand=(vcmd, '%S', '%s', '%d'))
        
        self.bind('<FocusIn>' , self.focusin)
        self.bind('<FocusOut>', self.focusout)
        self.bind('<Key>'     , self.check)
    
    #rewire .insert() to be a proxy of .input
    def validate(self, action_text, orig_text, action):
        if action == '1':
            if orig_text == self.__ph:
                self.input = action_text
            
        return True
    
    #removes placeholder if necessary    
    def focusin(self, event=None):
        if self.isholder:
            self.input = ''
    
    #adds placeholder if necessary    
    def focusout(self, event=None):
        if self.isempty:
            self.input = self.__ph
    
    #juggles the placeholder while you type    
    def check(self, event):
        if event.keysym == 'BackSpace':
            if self.input and len(self.input) == 1:
                self.input = self.__ph
                self.icursor(0)
                return 'break'
        elif self.isholder:
            if event.char:
                self.input = ''
            else:
                return 'break'


用法示例:


usage example:

#__main__.py

import tkinter as tk
import widgets as ctk #custom tk                
                

if __name__ == "__main__":
    root = tk.Tk()
    root.title("Placeholder Entry")
    root.grid_columnconfigure(2, weight=1)

    #init some data
    entries    = [] #for storing entry references
    label_text = ['email', 'name']
    entry_text = ['you@mail.com', 'John Smith']

    #create form
    for n, (label, placeholder) in enumerate(zip(label_text, entry_text)):
        #make label
        tk.Label(root, text=f'{label}: ', width=8, font='consolas 12 bold', anchor='w').grid(row=n, column=0, sticky='w')
        #make entry
        entries.append(ctk.PlaceholderEntry(root, placeholder, width=14, font='consolas 12 bold'))
        entries[-1].grid(row=n, column=1, sticky='w')

    #form submit function
    def submit():
        for l, e in zip(label_text, entries):
            if e.input:
                print(f'{l}: {e.input}')

    #form submit button        
    tk.Button(root, text='submit', command=submit).grid(column=1, sticky='e')

    root.mainloop()
        
    
    

这篇关于以程序方式向 tkinter Entry 小部件添加占位符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆