2014-10-22 2 views
3

У меня есть ползунок, который обновляет запись при изменении, и эта запись обновляет слайдер при изменении. В основном оба они представляют одно и то же значение, но с двумя различными способами ввода. Соответствующие методы выглядеть следующим образом (в сокращенном виде):Почему Tkinter.StringVar(). Get() пытается создать собственное значение как целое число?

class MyWindow(Frame): 

    def __init__(self, master=None): 
     Frame.__init__(self, master) 
     self.pack(fill=BOTH, expand=1) 
     self.makeWidgets() 

    def makeWidgets(self): 

     #controls to set the radius of a circle 
     #slider 
     self.radSlider = Scale(self, command=self.updateEntry) 
     self.radSlider.pack() 

     #entry 
     self.radVar = StringVar() 
     vcmd = (self.master.register(self.validateInt), 
      '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') 
     self.radEntry = Entry(self, 
           validate = 'key', 
           validatecommand = vcmd, 
           textvariable=self.radVar) 
     self.radEntry.pack() 
     self.radVar.trace("w", self.updateSlide) 

    def updateEntry(self, *event): 
     rad = event[0]#first element of event is value of slider, as string 
     self.radVar.set(rad) 

    def updateSlide(self, *event): 
     if not self.radVar.get():#if entry is an empty string, set slider to zero 
      value = 0 
     else: 
      value = int(self.radVar.get()) 
     self.radSlider.set(value)   

    def validateInt(self, action, index, value_if_allowed, prior_value, text, *args): 
    """ 
    validates an entry to integers and empty string only 
    """ 
     if (value_if_allowed == ""): 
      return True 
     if text in '': 
      try: 
       int(value_if_allowed) 
       return True 
      except: 
       return False 
     else: 
      return False 

Он отлично работает, но когда radEntry пустая строка:

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__ 
    return self.func(*args) 
    File "C:\Users\ntopper\Desktop\Collector\NewObjDialog.py", line 127, in update Slide 
    if not self.radVar.get(): 
    File "C:\Python27\lib\lib-tk\Tkinter.py", line 283, in get 
    return getint(self._tk.globalgetvar(self._name)) 
ValueError: invalid literal for int() with base 10: '' 

Один из способов, чтобы никогда не позволить запись быть пустая строка, но с нулем, который не может быть удален в поле ввода, мягко раздирает. (чтобы установить поле в 241, вы сначала установите поле на 410, затем на 41, затем на 241)

Другой вариант - просто проигнорировать сообщение об ошибке, поскольку оно не разбивает мою программу, но это не так. ,

Кажется, что Tkniter.StringVar(). Get() пытается использовать собственное строковое значение как целое, почему это?

+0

На данный момент я собираюсь изменить «if/else» в методе «updateSlide» на «try/except», поэтому я не вижу ошибку значения и все еще имею правильное поведение. Но я все еще хочу знать, почему это делается. –

+0

Многие вопросы Python, включая этот, нуждаются в точной версии Python для правильного ответа. См. Мой ответ ниже. –

ответ

1

Вот простейший is_int (или пустой), который я только что написал для диалога Idle.

# at module level 
def is_int(s): 
    "Return 's is blank or represents an int'" 
    if not s: 
     return True 
    try: 
     int(s) 
     return True 
    except ValueError: 
     return False 
... 
# inside widget_subclass.__init__ 
     self.is_int = self.register(is_int) 
... 
# inside widget_subclass method 
      Entry(entry_area, textvariable=var, validate='key', 
       validatecommand=(self.is_int, '%P') 
       ).grid(row=row, column=1, sticky=NSEW, padx=7) 

Что касается вашей ошибки, когда я исправить Validate строку документации отступа, как так

def validateInt(self, action, index, value_if_allowed, prior_value, text, *args): 
     """validates an entry to integers and empty string only""" 
     if value_if_allowed == "": 

и работать с 2.7.8 на Win7, код нормально без сообщений об ошибках работы. Изменение слайдера или текста меняет другой, как вы его разработали.

Глядя на мою копию Python27\lib\lib-tk\Tkinter.py,

return getint(self._tk.globalgetvar(self._name)) 

находится на линии 321 внутри IntVar.get метода, где я ожидал его. Строка 283, как и в предыдущем примере трассировки, находится в docstring StringVar.__init__. Поэтому я полагаю, что вы используете более раннюю версию 2.x и что ваша копия Tkinter.py имеет серьезную ошибку.

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