Как мне получить этот код проверки, чтобы ограничить длину символа и разрешить только цифры - PullRequest
0 голосов
/ 27 марта 2020

Я создаю форму ввода даты рождения для своего заявления и хочу сделать так, чтобы они могли только вводить числа и ограничивать введенные числа максимально необходимой суммой, например, 2 в день. Когда я пытался реализовать это, он даже не позволял мне что-либо делать в виджетах ввода. Как я могу ограничить длину символа и принимать только цифры?

def onlyNumbers(char):
    if (len(dayE.get()) >= 2):
        return False
    elif (len(monthE.get()) >= 2):
        return False
    elif (len(yearE.get()) >= 4):
        return False
    elif (char is ""):
        return True
    else:
        return char.isdigit()
dayV = tk.StringVar(self, value = "DD")
monthV = tk.StringVar(self, value = "MM")
yearV = tk.StringVar(self, value = "YYYY")
validation = self.register(onlyNumbers)

dayE = tk.Entry(self, font = BASIC_FONT, textvariable = dayV, width = 5, justify = "center")
dayE.pack()
dayE.config(validate = "key", validatecommand = (validation, "%P"))

monthE = tk.Entry(self, font = BASIC_FONT, textvariable = monthV, width = 5, justify = "center")
monthE.pack()
monthE.config(validate = "key", validatecommand = (validation, "%P"))

yearE = tk.Entry(self, font = BASIC_FONT, textvariable = yearV, width = 5, justify = "center")
yearE.pack()
yearE.config(validate = "key", validatecommand = (validation, "%P"))

1 Ответ

1 голос
/ 28 марта 2020

Вопрос : Entry проверка, чтобы ограничить длину символа и разрешить только цифры

В этом примере реализовано:

  • Разрешить только ввод цифр
  • Ограничить количество цифр согласно 'DD', 'MM', 'YYYY'
  • Разрешить начальные нули в 'DD', 'MM'
  • Разрешить только диапазоны чисел, 1, 31, 1, 12 и аргумент years=(<from>, <to>)
  • Возвращает отредактированные данные в виде: {'month': 3, 'day': 28, 'year': 2020}

Ссылка :

  • VALIDATION

    Проверка выполняется путем установки опции validatecommand= для сценария (validateCommand), который будет оцениваться в соответствии с параметром validate=.
    Объяснение использованных процентных замен ('%W', '%V', '%v', '%P', '%S')

  • SO: интерактивно проверяющая запись-виджет-содержимое-в-tkinter

    Обратите внимание на заметку там :
    Примечание: важно, чтобы команда проверки вернула либо True, либо False. Все остальное приведет к отключению проверки.


Примечание :
Проверка получит OFF , если текст Entry изменился, либо с помощью .insert(..., .delete(... или <textvariable>.set(...).


import tkinter as tk


class DateEntry(tk.Frame):
    def __init__(self, parent, **kwargs):
        years = kwargs.pop('years', (1900, 9999))
        super().__init__(parent, **kwargs)

        vcmd = (self.register(self._validate), '%W', '%V', '%v', '%P', '%S')

        for name, text, v1, v2 in (('day', 'DD', 1, 31),
                                   ('month', 'MM', 1, 12),
                                   ('year', 'YYYY', years[0], years[1])):
            e = tk.Entry(self, name=name, width=len(text) + 1, justify="center")
            e.pack(side=tk.LEFT)
            e.insert(0, text)
            e._valid = (len(text), v1, v2)
            e.config(validate="all", validatecommand=vcmd)

    def get(self):
        data = {}
        for entry in [self.nametowidget(child) for child in self.children]:
            text = entry.get()
            data[entry.winfo_name()] = int(text) if text.isdigit() else None
        return data

    def _validate(self, widget, cmd, validate, value, text):
        # get this entry reference
        w = self.nametowidget(widget)

        # Clear entry or do nothing
        if cmd in ('focusin', 'forced') or value == '':
            if not value.isdigit():
                w.delete(0, tk.END)
                # Set the 'validate' option again after edit
                w.after_idle(w.config, {'validate': validate})
            return True

        # process key
        elif cmd == 'key' and value.isdigit():
            # get from this entry the valid parameter
            l, v1, v2 = w._valid

            # get the startswith chars if YYYY
            if v1 > 1 and len(value) < l:
                l2 = len(value)
                v1, v2 = int(str(v1)[:l2]), int(str(v2)[:l2])

            # allow leading zero in DD / MM
            elif v1 == 1 and len(value) == 1 and int(value) == 0:
                return True

            # return True if all valid else False
            return all((text.isdigit(), v1 <= int(value) <= v2, len(value) <= l))

        # else return False
        return False

Использование :

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        tk.Button(self, text='print date', command=self.print_date).grid()

        self.date_entry = DateEntry(self, years=(2000, 2020))
        self.date_entry.grid()

    def print_date(self):
        print('print_date: {}'.format(self.date_entry.get()))
        # >>> print_date: {'month': 3, 'day': 28, 'year': 2020}


if __name__ == "__main__":
    App().mainloop()

Протестировано с Python: 3,5 - 'TclVersion': 8,6 'TkVersion': 8,6

...