自动向 tkinter 中的输入框添加破折号 [英] Auto add dashes to entryboxes in tkinter
本文介绍了自动向 tkinter 中的输入框添加破折号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
当用户输入他们的电话号码时,有没有办法在电话号码中自动添加破折号,比如电话号码是 5551111234,但是当他们在输入框中输入时,该号码应该显示为带有连字符 b/w 的号码自动喜欢555-1111234.
Is there a way to auto add dashes in a phone number when the person types their phone number like for say phone number is 5551111234, but when they type it in the entry box the number should appear with hyphen b/w the number automatically like 555-1111234.
推荐答案
这是一个复杂的例子,但它处理的不仅仅是电话号码.被评论死了.
This is a complex example, but it handles more than just phone numbers. It is commented to death.
#widgets.py
import tkinter as tk, re
from dataclasses import dataclass, field
from typing import List, Pattern, Iterable
from copy import deepcopy
Char: Pattern = re.compile('[a-z0-9]', re.I)
''' FormEntryFormat_dc
this serves as a configuration for the behavior of FormEntry
'''
@dataclass
class FormEntryFormat_dc:
valid :Pattern = None #pattern to validate text by
separator :str = None #the separator to use
marks :List = field(default_factory=list) #list of positions to apply separator
strict :bool = False #True|False strict typing
def config(self, ascopy:bool=True, **data):
c = deepcopy(self) if ascopy else self
for key in c.__dict__:
if key in data:
c.__dict__[key] = data[key] #assign new value
return c
#prepare a few formats
TimeFormat = FormEntryFormat_dc(re.compile('^(\d{1,2}(:(\d{1,2}(:(\d{1,2})?)?)?)?)?$' ), ':' , [2, 5])
DateFormat = FormEntryFormat_dc(re.compile('^(\d{1,2}(\\\\(\d{1,2}(\\\\(\d{1,4})?)?)?)?)?$'), '\\', [2, 5])
PhoneFormat = FormEntryFormat_dc(re.compile('^(\d{1,3}(-(\d{1,3}(-(\d{1,4})?)?)?)?)?$' ), '-' , [3, 7], True)
PhoneFormat2 = FormEntryFormat_dc(re.compile('^(\d{1,3}(-(\d{1,7})?)?)?$' ), '-' , [3] , True)
''' FormEntry
an entry with format behavior
'''
class FormEntry(tk.Entry):
@property
def input(self) -> str:
return self.get()
def offset(self, separator:str, marks:Iterable):
sep_marks = [] #cache for positions of already inserted separators
offset = 0 #the overall offset between inserted and expected separator marks
#get a mark for every current separator
for i, c in enumerate(self.input):
if c == separator:
sep_marks.append(i)
#if any sep_marks ~ subtract the value of sep_marks last index
#~from the value of the corresponding index in marks
n = len(sep_marks)
if n:
offset = max(0, marks[n-1]-sep_marks[-1])
return offset
def __init__(self, master, frmt:FormEntryFormat_dc, **kwargs):
tk.Entry.__init__(self, master, **kwargs)
self.valid = frmt.valid
if self.valid:
#register validatecommand and assign to options
vcmd = self.register(self.validate)
self.configure(validate="all", validatecommand=(vcmd, '%P'))
if frmt.marks and frmt.separator:
#bind every key to formatting
self.bind('<Key>', lambda e: self.format(e, frmt.separator, frmt.marks, frmt.strict))
def validate(self, text:str):
return not (self.valid.match(text) is None) #validate with regex
def format(self, event, separator:str, marks:Iterable, strict:bool):
if event.keysym != 'BackSpace': #allow backspace to function normally
i = self.index('insert') #get current index
if Char.match(event.char) is None and (i in marks or not strict):
event.char = separator #overwrite with proper separator
else:
#automatically add separator
if i+self.offset(separator, marks) in marks:
event.char = f'{separator}{event.char}'
self.insert(i, event.char) #validation will check if this is allowed
return 'break'
#main.py (OOP style)
import widgets as ctk #custom tk
import tkinter as tk
class Main(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("Formatted Entry")
self.grid_columnconfigure(2, weight=1)
#create labels
self.labels = ['time', 'date', 'phone', 'phone2']
for n, label in enumerate(self.labels):
tk.Label(self, text=f'{label}: ', width=14, font='consolas 12 bold', anchor='w').grid(row=n, column=0, sticky='w')
#create entries
self.entries = []
for n, format in enumerate([ctk.TimeFormat, ctk.DateFormat, ctk.PhoneFormat, ctk.PhoneFormat2]):
self.entries.append(ctk.FormEntry(self, format, width=14, font='consolas 12 bold'))
self.entries[-1].grid(row=n, column=1, sticky='w')
#form submit button
tk.Button(self, text='submit', command=self.submit).grid(column=1, sticky='e')
def submit(self):
for l, e in zip(self.labels, self.entries):
print(f'{l}: {e.input}')
Main().mainloop() if __name__ == "__main__" else None
#main.py (procedural style)
import widgets as ctk #custom tk
import tkinter as tk
if __name__ == "__main__":
root = tk.Tk()
root.title("Formatted Entry")
root.grid_columnconfigure(2, weight=1)
#create labels
labels = ['time', 'date', 'phone', 'phone2']
for n, label in enumerate(labels):
tk.Label(root, text=f'{label}: ', width=14, font='consolas 12 bold', anchor='w').grid(row=n, column=0, sticky='w')
#create entries
entries = []
for n, format in enumerate([ctk.TimeFormat, ctk.DateFormat, ctk.PhoneFormat, ctk.PhoneFormat2]):
entries.append(ctk.FormEntry(root, format, width=14, font='consolas 12 bold'))
entries[-1].grid(row=n, column=1, sticky='w')
def submit():
for l, e in zip(labels, entries):
print(f'{l}: {e.input}')
#form submit button
tk.Button(root, text='submit', command=submit).grid(column=1, sticky='e')
root.mainloop()
这篇关于自动向 tkinter 中的输入框添加破折号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文