2014-01-03 2 views
-1

Как часть моей программы, я прошу пользователя указать свое имя и класс (класс средней школы). Когда пользователь нажимает «Enter» после ввода своего имени, кнопка отключается, и появляется поле «tutor». Тем не менее, пользователь по сути может представить свое имя, даже если они ничего не набрали. Я хочу, чтобы только кнопка «Ввод» активировалась после того, как пользователь начал вводить текст.Событие ввода текста?

То, что я сделал ниже, кажется, не работает :(

Кроме того, мои проверки входных данных не работают - знают, почему

class Enter_Name_Window(tk.Toplevel): 
    '''A simple instruction window''' 
    def __init__(self, parent): 
     tk.Toplevel.__init__(self, parent) 
     self.text = tk.Label(self, width=40, height=2, text= "Please enter your name and class.") 
     self.text.pack(side="top", fill="both", expand=True) 

     name_var = StringVar() 
     def validate_enter_0(): 
      self.Enter_0.config(state=(NORMAL if name_var.get() else DISABLED)) 
      print("validate enter worked") 

     name_var.trace('w', lambda name, index, mode: validate_enter_0) 
     enter_name = Entry(self, textvariable=name_var) 
     enter_name.pack() 
     enter_name.focus_set() 


     def callback(): 
      if len(name_var) > 10 or any(l not in string.ascii_letters for l in name_var): 
       print("Input validation worked") 

      self.display_name = tk.Label(self, width=40, height=2, text = "Now please enter your tutor group.") 
      self.display_name.pack(side="top", fill="both", expand=True) 


      tutor_var = StringVar() 
      def validate_enter_2(): 
       self.Enter_0_2.config(state=(NORMAL if tutor_var.get() else DISABLED)) 
       print("validate enter worked") 
      tutor_var.trace('w', lambda name, index, mode: validate_enter_0_2) 
      tutor = Entry(self, textvariable=tutor_var) 
      tutor.pack() 
      tutor.focus_set() 

      self.Enter_0.config(state="disabled") 

      self.Enter_0_2 = Button(self, text="Enter", width=10, command=self.destroy) 
      self.Enter_0_2.pack() 


     self.Enter_0 = Button(self, text="Enter", width=10, command=callback) 
     self.Enter_0.pack() 
+0

http://stackoverflow.com/questions/16687124/python-tkinter-disable-the-button-until-all-the-fields-are-filled –

+0

Подразумевается ли это как [предыдущий вопрос] http://stackoverflow.com/questions/20622044/how-to-i-create-an-event-for-user-entry/20622282#comment31391807_20622282), или совершенно новый вопрос, который каким-то образом отличается? (И, если последнее, каким образом оно отличается?) – abarnert

+0

Кроме того, как я уже говорил вам по предыдущему вопросу, предоставьте [SSCCE] (http://sscce.org) - что-то, что мы можем запустить и отладить Вместо простого фрагмента кода. – abarnert

ответ

1

Первой очевидная проблема эта линия:

?
tutor_var.trace('w', lambda name, index, mode: validate_enter_0_2) 

Вы создали функцию, которая принимает три переменные, и возвращает функцию validate_enter_0_2 как объект функции. Это не делает ничего хорошего.

Вы хотите создать функцию, которая звонитvalidate_enter_0_2 функция. Как это:

tutor_var.trace('w', lambda name, index, mode: validate_enter_0_2()) 

У вас есть точно такая же проблема с name_var и будет также необходимо зафиксировать его там, конечно.


Кроме того, вы на самом деле не имеют функция с именем validate_enter_0_2 называть, потому что вы определили его как validate_enter_2. Это означает, что ваша функция проверки просто добавляет NameError вместо того, чтобы делать полезные действия. Или, если у вас есть функция validate_enter_2, определенная где-то еще в вашем коде, она вызывает неправильную функцию. (Это одна из причин, что загадочные имена, как enter_0_2 и enter_2 не очень хорошая вещь.)


Там, по крайней мере одна другая проблема с кодом: Вы неоднократно пытался использовать name_var, который является StringVar объект , как если бы это была строка. Вы не можете этого сделать. И если вы на самом деле смотреть на выходе консоли Tkinter расскажет вам об этом, с tracebacks, как это:

Exception in Tkinter callback 
Traceback (most recent call last): 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1410, in __call__ 
    return self.func(*args) 
    File "tkval2.py", line 25, in callback 
    if len(name_var) > 10 or any(l not in string.ascii_letters for l in name_var): 
AttributeError: StringVar instance has no attribute '__len__' 

И это исключение происходит, прежде чем вы получите возможность создать новый Entry.

Чтобы исправить это, вам нужно позвонить get на StringVar всякий раз, когда вы хотите получить его значение, например:

if len(name_var.get()) > 10 or any(l not in string.ascii_letters for l in name_var.get()) 

Наконец, как я объяснил в ответ на ваш другой вопрос, ваш валидатор trace не будет вызван, пока что-то не изменится. Это означает, что вам нужно либо вызвать его явно, либо явно name_var.set(''), либо просто отключить кнопку. Как написано, он будет включен, и только отключите, если вы напечатаете что-то, а затем удалите его.


Я не уверен, является ли это единственные проблемы с вашим кодом, но все они, безусловно, предотвратить вашу проверку работать, как ожидалось.Таким образом, вам нужно исправить все их и любые другие ошибки в коде, прежде чем он будет работать.


Из ваших комментариев:

Однако я задавался вопросом, как создать всплывающее сообщение об ошибке, отображающее ...

Когда вы хотите сделать это? Какое условие вы хотите проверить, и когда вы хотите его проверить?

Во всяком случае, как и в большинстве графических интерфейсов, способ «всплывать» - это диалог. Dialog Windows в книге Tkinter объясняет все, что вам нужно знать. Но вам не нужно копировать-вставлять весь этот код или писать его с нуля; stdlib поставляется с Tkinter helper modules, которые выполняют большую часть работы для вас. В вашем случае вы, вероятно, просто хотите tkMessageBox.

... и что-то, что заставляет пользователя повторно ввести их имя

принуждать их как? Просто удаление существующего содержимого Entry оставит их с пустым полем для заполнения, что также отключит кнопку. Это то, что вы хотите?

Во всяком случае, догадываясь, что вы хотите, это может выглядеть примерно так:

def callback(): 
    if len(name_var.get()) > 10: 
     tkMessageBox.showerror("Bad name", "Your name is too long. What's wrong with good American names like Joe?") 
     name_var.set('') 
     return 
    # the rest of your code here 

В callback функции (вызывается при нажатии на кнопку после ввода их имя), вместо того, чтобы просто проверить некоторое условие и распечатав что-то, я проверяю условие и вывожу диалоговое окно с ошибкой, очищаю существующее имя и возвращаю раньше, а не создаю вторую половину формы. Я не обрабатывал ваше другое условие (любые буквы, отличные от ASCII), но должно быть очевидно, как добавить это.

Однако подтверждение такого действия может быть сделано лучше всего посредством фактической проверки - вместо того, чтобы заставить их ждать, пока они не нажмут кнопку, поймайте его, как только они попытаются ввести 11-й символ, или пробел или акцентированный символ, или что-то еще иначе вам не понравится. Затем вы можете открыть окно сообщения и либо отключить кнопку, пока не исправит ее, не отклоните/не отмените изменение (что проще с функцией validatecommand, чем с функцией trace, как показано в ответе на ваш предыдущий вопрос).

Последнее: Вместо окна сообщения может быть лучше просто вставить ошибку, как, например, ярлык, который появляется в самой форме (возможно, с описанием ошибки в красном цвете с большим значком) , Это распространено в веб-приложениях и в более современных графических интерфейсах, поскольку обеспечивает более немедленную обратную связь и менее навязчиво для пользовательского потока.

+0

Спасибо, что работают валидация и обработчик событий.Мне, однако, интересно, как создать всплывающее сообщение с отображением ошибки и что-то, что заставляет пользователя вводить свое имя. Спасибо – user3056786

+0

@ user3056786: Это несколько неопределенные вопросы. Они также кажутся последующими, что должно быть одним или несколькими отдельными вопросами. Но я отредактирую ответ, чтобы попытаться начать работу. – abarnert

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