Tkinter Формат текста на входе
Форматирование текста в формате времени по типу пользователя
Я пытаюсь отформатировать текст в стандартный формат времени 00:00:00
в текстовом поле Tk.Entry, когда пользователь вводит цифры.
Я понимаю, что Tkinter - не самая простая и не лучшая оптимизированная среда для форматирования текста, когда пользователь печатает, но мне удалось продвинуться так далеко:
from Tkinter import *
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
def createWidgets(self):
sv = StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: self.entryUpdateEndHour(sv))
endHourEntry = Entry(self, textvariable=sv)
endHourEntry.pack()
def entryUpdateEndHour(self, sv):
global x
x = sv.get()[0:2] + ':'
y = x + sv.get()[3:5] + ':'
z = y + sv.get()[6:8]
sv.set(z)
root = Tk()
app = Application(master=root)
app.mainloop()
Это распечатывает именно то, что я хочу (12:45:67
), но живое форматирование плохо. Например, при наборе двух чисел я получаю 12:::
в текстовом поле, и он пропускает каждый третий номер, который я ввожу, так как он заменяет его на :
,
Я был бы очень признателен, если у кого-нибудь есть обходные пути или решения для этого ответа. Заранее спасибо.
2 ответа
Вот мое решение:
from Tkinter import *
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
def createWidgets(self):
sv = StringVar()
endHourEntry = Entry(self, textvariable=sv)
sv.trace("w", lambda name, index, mode, sv=sv:
entryUpdateEndHour(endHourEntry))
endHourEntry.pack()
def entryUpdateEndHour(entry):
text = entry.get()
if len(text) in (2,5):
entry.insert(END,':')
entry.icursor(len(text)+1)
elif len(text) not in (3,6):
if not text[-1].isdigit():
entry.delete(0,END)
entry.insert(0,text[:-1])
if len(text) > 8:
entry.delete(0,END)
entry.insert(0,text[:8])
root = Tk()
app = Application(master=root)
app.mainloop()
Для меня проще работать с виджетом ввода, а не напрямую с StringVar. Единственная причина, по которой вообще нужно включить stringvar, - получить поведение трассировки, чтобы обратный вызов вызывался правильно. Другим вариантом будет сделать что-то с vcmd
опцию конструктора Entry, но я не могу сделать это обновить запись... Только проверить содержимое.
from Tkinter import *
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
def createWidgets(self):
sv = StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: self.entryUpdateEndHour(sv))
self.endHourEntry = Entry(self, textvariable=sv)
self.endHourEntry.pack()
print [x for x in dir(self.endHourEntry) if 'set' in x]
def entryUpdateEndHour(self, sv):
digits = filter(str.isdigit, sv.get())
sv.set('{}:{}:{}'.format(digits[:2], digits[2:4], digits[4:]))
self.endHourEntry.icursor(END)
root = Tk()
app = Application(master=root)
app.mainloop()
Проблема: курсор всегда идет до конца. Я понятия не имею об этом.