【问题标题】:How to I create an event for user entry?如何为用户输入创建事件?
【发布时间】:2014-01-04 12:00:32
【问题描述】:

作为我程序的一部分,我要求用户提供他们的姓名和班级(高中班级)。我正在使用一个成功接受输入的文本输入功能,但我需要验证方面的帮助:我只希望在用户实际开始输入后激活“输入”按钮,否则用户将按下“输入”按钮和停用它。另外,我想确保当他们输入他们的名字时,程序只接受字母而不接受数字。对于第二个条目(学校班级/导师班级),用户将输入类似 6A1 的内容,这是他们的班级。我的学校大约有 10 个不同的高级班级,那么我如何验证条目以仅接受这 10 个班级中的 1 个或可能是下拉菜单?非常感谢您的帮助:)

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)

        enter_name = Entry(self)
        enter_name.pack()
        enter_name.focus_set()


        def callback():
            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 = Entry(self)
            tutor.pack()
            tutor.focus_set()
            Enter_0.config(state="disabled")

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


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

【问题讨论】:

    标签: python events input menu tkinter


    【解决方案1】:

    按照您的字面意思进行操作的方法是,“一旦用户实际开始输入,'Enter' 按钮将变为活动状态”是绑定enter_name 上的更改或按键事件,并在它激活后激活Enter_0触发。

    但这可能不是你真正想要的。如果用户输入一些文本然后删除它,如果再次禁用按钮会更好吗?如果用户在没有输入任何内容的情况下粘贴了一些文本,那不应该启用按钮吗?

    为此,您需要以下两项之一:验证或变量跟踪。


    在我们开始之前,您几乎肯定会希望将Enter_0 按钮作为属性存储在self 上,而不是在彼此之上创建和重新创建新按钮。所以,我将在我的示例中这样做。


    验证,虽然它在 Tkinter 中的记录非常糟糕并且使用起来有点笨拙,但它非常强大,并且显然适合您正在尝试做的事情 - 验证文本:

    def __init__(self, parent):
    
        # existing stuff
    
        vcmd = self.root.register(self.validate)
        enter_name = Entry(self, validate='key', validatecommand=(vcmd, '%P'))
    
        # existing stuff
    
        self.Enter_0 = Button(self, text="Enter", width=10, command=callback)
        self.Enter_0.pack()
    
    def validate(self, P):
        self.Enter_0.config(state=(NORMAL if P else DISABLED))
        return True
    

    这可能看起来像是难以理解的魔法,Tkinter 文档没有给你任何指导。但是validatecommand 的 Tk 文档显示了它的含义:

    • key 位表示该命令“将在条目被编辑时被调用”。
    • %P 表示“允许编辑时条目的值”。您可以将任意数量的% 字符串粘贴到vcmd 中,它们将作为参数传递给validate 方法。所以,你可以传递(vcmd, '%s', '%P', '%v'),然后定义validate(self, s, P, v)
    • 您可以在函数中做任何您想做的事情,然后返回 TrueFalse 以接受或拒绝更改(或返回 None 以停止调用您的验证函数)。

    无论如何,现在,如果用户尝试以任何方式编辑条目,那么如果他们的编辑会给您一个非空字符串,那么Enter_0 按钮将设置为NORMAL,否则DISABLED


    变量跟踪在概念上要笨重得多,但实际上通常更简单。它也没有完全记录,但至少它有些记录了。

    这个想法是创建一个StringVar,将其附加到Entry,并在其上放置一个“写入跟踪”,这是一个在每次更新变量时都会调用的函数(每次更新都会发生这种情况) Entry 更改内容)。像这样:

    def __init__(self, parent):
    
        # existing stuff
    
        name_var = StringVar()
        def validate_enter():
            self.Enter_0.config(state=(NORMAL if var.get() else DISABLED))
        name_var.trace('w', lambda name, index, mode: validate_enter)
        enter_name = Entry(self, textvariable=name_var)
    
        # existing stuff--and again, do the self.Enter_0 change
    

    【讨论】:

    • 我收到来自 vcmd = self.root.register(self.validate) 的错误?
    • 我很困惑为什么 enter_name = Entry 被定义了两次?
    • @user3056786 大概你在任何地方都没有self.root,我假设你有。您可能想要self.parent,或全局root 或类似的。 (顺便说一句,在未来,不要只说“我遇到错误”,发布实际错误和回溯,这样人们就可以准确地阅读问题所在,而不必猜测。)
    • @user3056786:同时,我展示了两个不同的选项来解决您的问题,每个选项都只定义了一次 enter_name。如果你想做 both 选项(可能没有充分的理由这样做),你可以,但你必须将两组更改合并到原始代码中,而不是复制和粘贴两者(在其他单词,定义一次enter_name,同时传递validate args 和textvariable arg)。
    • @user3056786:我已经为您的代码创建了一个精简、清理的版本,并放置了每个替代方案herehere 的完整工作版本,以便更好地向您展示这个想法。
    猜你喜欢
    • 2017-11-30
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 1970-01-01
    • 1970-01-01
    • 2014-11-06
    相关资源
    最近更新 更多