文字录入活动?

时间:2014-01-03 19:26:10

标签: python user-interface events tkinter tkinter-entry

作为我课程的一部分,我向用户询问他们的姓名和班级(高中班级)。用户在输入姓名后按“Enter”键,按钮将被禁用,并显示“tutor”字段。然而,即使用户没有输入任何内容,用户实际上也能够提交他们的名字。我只希望在用户开始输入后“Enter”按钮处于活动状态。

我在下面所做的事似乎不起作用:(

另外,我的输入验证不起作用 - 知道原因吗?

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()

1 个答案:

答案 0 :(得分: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_2enter_2这样神秘的名字不是一件好事的一个原因。)


您的代码至少还有一个问题:您反复尝试使用name_var StringVar对象,就好像它是一个字符串一样。你不能这样做。如果您实际查看控制台输出,Tkinter会告诉您这一点,并带有这样的追溯:

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('')调用它,或者只是禁用禁用按钮。如上所述,它将启动,并且只有在您键入内容然后将其删除时才会禁用。


我不确定这些是您代码中唯一的问题,但所有这些问题肯定会阻止您的验证按预期工作。因此,您需要先修复所有这些错误以及代码中的任何其他错误,然后再进行操作。


来自您的评论:

  

但我想知道如何创建一个显示错误的弹出消息...

你想什么时候做?您想检查什么条件,以及何时检查它?

无论如何,就像在大多数GUI中一样,“弹出”这样的东西的方式是一个对话框。 Tkinter书中的Dialog Windows解释了你需要知道的一切。但是您不需要复制粘贴所有代码,也不需要从头开始编写代码; 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功能更容易,如我所示回答你之前的问题)。

最后一件事:代替消息框,最好只是将错误嵌入,例如,表单中出现的标签(可能带有红色的错误描述,带有一个大标志图标)。这在Web应用程序和更现代的GUI中很常见,因为它提供了更直接的反馈,并且不那么突出用户流。