2015-07-01 3 views
2

Я пытаюсь использовать этот отличный ответ Брайана Oakley, но безрезультатно (https://stackoverflow.com/a/4140988/5060127) ...Tkinter со счётчиком диапазон проверка

Я хотел бы использовать тот же метод для проверки значений со счётчиком. Я определил from_ и значения для spinboxes, но пользователь все еще может набирать в них что-то больше ... он должен быть проверен, что только значения внутри диапазона from_-to могут быть введены пользователем, и только целые числа.

Вот код, который показывает, как далеко я получил ...

try: 
    from Tkinter import * 
except ImportError: 
    from tkinter import * 

class GUI: 
    def __init__(self): 
     # root window of the whole program 
     self.root = Tk() 
     self.root.title('ImageSound') 

     # registering validation command 
     vldt_ifnum_cmd = (self.root.register(self.ValidateIfNum),'%s', '%S') 

     # creating a spinbox 
     harm_count = Spinbox(self.root, from_=1, to=128, width=5, justify='right', validate='all', validatecommand=vldt_ifnum_cmd) 
     harm_count.delete(0,'end') 
     harm_count.insert(0,8) 
     harm_count.pack(padx=10, pady=10) 

    def ValidateIfNum(self, s, S): 
     # disallow anything but numbers 
     valid = S.isdigit() 
     if not valid: 
      self.root.bell() 
     return valid 

if __name__ == '__main__': 
    mainwindow = GUI() 
    mainloop() 
+0

Но ваш метод 'ValidateIfNum' * не применяет эту проверку диапазона. – jonrsharpe

+0

Проблема заключается в том, что виджет 'Spinbox' не предоставляет параметры' validate' и 'validatecommand'. Они принимаются, но (я думаю, это так), они игнорируются. – Tupteq

+0

Но я настроил validatecommand точно, как Брайан положил его - используя .register ... См. Ссылку. Я хотел бы выяснить, почему .isdigit не делает то, что он должен делать, до того, как я продолжаю и выполняю проверку диапазона ... Пример Bryan работает, когда я меняю sw = '' valid = (S.lower() = = S) 'с' valid = S.isdigit() '... так почему же он не работает здесь? –

ответ

2

Я думаю, что я нашел эту проблему. Функция валидатора вызывается изначально с S='', и ваше условие S.isdigit() возвращает False, и функция больше не вызывается. Но после того, как я обновил состояние до valid = S == '' or S.isdigit(), он начал работать так, как ожидалось.

Конечно, вам, вероятно, понадобится еще более сложное условие (например, проверка значения в пределах диапазона), но похоже, что пустая строка должна пройти (по крайней мере, начальную) проверку.

+0

Ничего себе, это было так просто! Спасибо! И да, вы правы, isdigit возвращает False на пустой строке, и, похоже, это то, что отключало его. Он работает сейчас. Спасибо! Давайте посмотрим, смогу ли я каким-либо образом провести проверку диапазона ... Если вводится число за пределами диапазона, оно должно вернуться к последнему действительному номеру. –

+0

Я рад, что мог бы помочь, пожалуйста, подумайте о том, как это сделать. Проверка диапазона может быть более сложной, поскольку в валидаторе вы получаете только старое значение поля, а новое значение может зависеть от позиции каретки, выбранного текста и т. Д. – Tupteq

+0

Ну, замена% s включает в себя всю текстовую запись, поэтому я уверен, что я вам придется использовать это как-то в моих сравнениях, а также .delete/.insert, чтобы перезаписать пользовательский ввод вне диапазона ... Если я снова застрял, я отредактирую свой оригинальный пост, поэтому, пожалуйста, следите за это одно, если вы можете :) Отмечено, что ваш ответ был решен, тем временем. Это действительно помогло - вчера я терял весь день, пытаясь понять это (я очень новичок в Python и tkinter)! –

1

Я сделал это! Работает только целочисленный ввод и проверка диапазона, которая учитывает виджеты from_ и для значений! Возможно, он немного взломан, но он работает! Вот код для всех, кто интересуется:

try: 
    from Tkinter import * 
except ImportError: 
    from tkinter import * 

class GUI: 
    def __init__(self): 
     # root window of the whole program 
     self.root = Tk() 
     self.root.title('ImageSound') 

     # registering validation command 
     vldt_ifnum_cmd = (self.root.register(self.ValidateIfNum),'%P', '%S', '%W') 

     # creating a spinbox 
     harm_count = Spinbox(self.root, from_=1, to=128, width=5, justify='right', validate='all', validatecommand=vldt_ifnum_cmd) 
     harm_count.insert(0,8) 
     harm_count.delete(1,'end') 
     harm_count.pack(padx=10, pady=10) 

    def ValidateIfNum(self, user_input, new_value, widget_name): 
     # disallow anything but numbers in the input 
     valid = new_value == '' or new_value.isdigit() 
     # now that we've ensured the input is only integers, range checking! 
     if valid: 
      # get minimum and maximum values of the widget to be validated 
      minval = int(self.root.nametowidget(widget_name).config('from')[4]) 
      maxval = int(self.root.nametowidget(widget_name).config('to')[4]) 
      # check if it's in range 
      if int(user_input) not in range (minval, maxval): 
       valid = False 
     if not valid: 
      self.root.bell() 
     return valid 

if __name__ == '__main__': 
    mainwindow = GUI() 
    mainloop() 

Одна вещь, которую я заметил, это не совсем рабочий, если вы выбираете весь текст в со счётчиком, и вставить что-то не так, как текст. Это полностью нарушает валидацию. Тьфу.

+0

Я столкнулся с той же проблемой. Проблема в том, что если вы попытаетесь перезаписать выделенный текст, он будет интерпретироваться как два независимых события: удалить и затем вставить. Кажется, нет никакого способа узнать, будет ли после этого событием delete вставить. На самом деле нужно новое событие: перезаписать выделенный текст. – Todd

Смежные вопросы