如何为用户输入创建事件? [英] How to I create an event for user entry?

查看:115
本文介绍了如何为用户输入创建事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为我计划的一部分,我要询问用户姓名和班级(高中班级).我正在使用一个文本输入功能,该功能可以成功接受输入,但是我需要验证方面的帮助:我只希望一旦用户实际开始输入后就使"Enter"按钮处于活动状态,否则用户将按"Enter"按钮并停用它.另外,我想确保当他们输入名称时,该程序将只接受字母,而根本不接受数字.对于第二个条目(学校班级/辅导班),用户将输入类似于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()

解决方案

执行您真正要求的方法:一旦用户实际上开始输入,"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设置为DISABLED. /p>


从概念上讲,可变跟踪要笨拙得多,但实际上通常更简单.它也没有完全记录,但至少有一些记录.

这个想法是创建一个 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

As part of my program I am asking the user for their name and their class (high school class). I am using a text entry function which is successfully accepting the input but I need help on validation: I only want the 'Enter' button to become active once the user has actually started typing as otherwise the user will press the 'Enter' button and deactivate it. Also, I would like to make sure that when they enter their name the program will only accept letters and no numbers at all. For the second entry (school class/tutor class) the user will enter something like 6A1 which is their class. There are about 10 different senior classes in my school so how can I either validate the entry to accept only 1 of these 10 classes or perhaps a drop down menu? Help would be greatly appreciated :)

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

解决方案

The way to do what you literally asked, "the 'Enter' button to become active once the user has actually started typing" is to bind the change or keypress event on the enter_name, and activate Enter_0 once it's triggered.

But that's probably not what you actually want. If the user enters some text and then deletes it, wouldn't it be nicer if the button disabled again? And if the user pastes some text without typing anything, shouldn't that enable the button?

To do that, you want one of two things: validation, or variable tracing.


Before we get into it, you're almost certainly going to want to store the Enter_0 button as an attribute on self instead of creating and re-creating new buttons on top of each other. So, I'll do that in my example.


Validation, although it's very badly documented in Tkinter and a bit clumsy to use, is very powerful, and the obvious fit for what you're trying to do—validate text:

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

This probably looks like unreadable magic, and the Tkinter docs give you no guidance. But the Tk docs for validatecommand show what it means:

  • The key bit means that the command "will be called when the entry is edited".
  • The %P means the "value of the entry if the edit is allowed". You can stick as many of those % strings as you want into your vcmd, and they will be passed as arguments to your validate method. So, you could pass (vcmd, '%s', '%P', '%v') and then define validate(self, s, P, v).
  • You can do anything you want in the function, and then return True or False to accept or reject the change (or return None to stop calling your validation function).

Anyway, now, if the user attempts to edit the entry in any way, then the Enter_0 button will be set to NORMAL if their edit would give you a non-empty string, DISABLED otherwise.


Variable tracing is conceptually a lot clunkier, but in practice often simpler. It's also not completely documented, but at least it's somewhat documented.

The idea is to create a StringVar, attach it to the Entry, and put a "write trace" on it, which is a function that gets called every time the variable is updated (which happens every time the Entry changes contents). Like this:

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

这篇关于如何为用户输入创建事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆