-1

作为我程序的一部分,我询问用户他们的姓名和班级(高中班级)。一旦用户在输入他们的名字后按下“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()
4

1 回答 1

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. 这意味着您的验证功能只是提出 aNameError而不是有用的。或者,如果您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.

要解决此问题,您需要getStringVar想要获取其值时调用,如下所示:

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

最后,正如我在回答您的其他问题时所解释的那样,您的trace验证器在发生变化之前不会被调用。这意味着您要么需要显式调用它,要么显式调用它name_var.set(''),或者只是启动禁用按钮。如所写,它将开始启用,并且只有在您键入内容然后擦除它时才会禁用。


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


从您的评论中:

然而,我想知道如何创建一个显示错误的弹出消息......</p>

你想什么时候这样做?你想检查什么条件,你想什么时候检查?

无论如何,就像在大多数 GUI 中一样,“弹出”这样的任何东西的方式是一个对话框。Tkinter 书中的对话框窗口解释了你需要知道的一切。但是您不需要复制粘贴所有代码,或者从头开始编写;stdlib 带有Tkinter 辅助模块,可以为您完成大部分工作。在你的情况下,你可能只是想要tkMessageBox.

......以及迫使用户重新输入他们的名字的东西

怎么逼他们?只需删除现有的条目内容,就会留下一个空框来填充它们,这也会禁用按钮。那是你要的吗?

无论如何,猜测你想要什么,它可能看起来像这样:

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 中很常见,因为它提供了更即时的反馈,并且对用户流程的影响较小。

于 2014-01-03T19:37:30.297 回答