简体   繁体   English

Tkinter,Entry 小部件,是否可以检测输入文本?

[英]Tkinter, Entry widget, is detecting input text possible?

I have an Entry widget on a simple calculator.我在一个简单的计算器上有一个 Entry 小部件。 The user can choose to enter an equation via the keypad.用户可以选择通过键盘输入方程式。 I was wondering if there was a way to detect a character(from the keypad in my case) being typed into the Entry widget.我想知道是否有一种方法可以检测到输入到 Entry 小部件中的字符(在我的情况下来自键盘)。 So, focus is on the widget, user presses '4', it comes up on the widget... can I detect this act, for basic purposes of logging the input?所以,焦点在小部件上,用户按下“4”,它出现在小部件上......我可以检测到这种行为,以记录输入的基本目的吗?

Every time you press a key inside a Tkinter window, a Tkinter.Event instance is created.每次您在 Tkinter 窗口内按下一个键时, Tkinter.Event创建一个Tkinter.Event实例。 All you need to do is access that instance.您需要做的就是访问该实例。 Here is a simple script that demonstrates just how:这是一个简单的脚本,演示了如何:

from Tkinter import Tk, Entry

root = Tk()

def click(key):
    # print the key that was pressed
    print key.char

entry = Entry()
entry.grid()
# Bind entry to any keypress
entry.bind("<Key>", click)

root.mainloop()

key (being a Tkinter.Event instance) contains many different attributes that can be used to get almost any type of data you want on the key that was pressed. key (作为Tkinter.Event实例)包含许多不同的属性,可用于获取几乎任何类型的按下键的数据。 I chose to use the .char attribute here, which will have the script print what each keypress is.我选择在这里使用.char属性,这将使脚本打印每个按键是什么。

Yes.是的。 There are a few different ways to do this, in fact.事实上,有几种不同的方法可以做到这一点。

You can create a StringVar , attach it to the Entry , and trace it for changes;您可以创建一个StringVar ,将其附加到Entry ,并trace它的变化; you can bind all of the relevant events;您可以bind所有相关事件; or you can add a validation command that fires at any of several different points in the sequence.或者您可以添加一个验证命令,该命令在序列中的几个不同点中的任何一个触发。 They all do slightly different things.他们都做略有不同的事情。

When a user types 4 , there's a key event with just the 4 in it (which doesn't let you distinguish whether the user was adding 4 to the end, or in the middle, or replacing a whole selected word, or…), and then a modification event is fired with the old text,* and then the "key" or "all" validation function is called with the (proposed) new text, and the variable is updated with the (accepted) new text (unless the validation function returned false, in which case the invalidcommand is called instead).当用户输入4 ,有一个只包含4的关键事件(这不会让您区分用户是在末尾添加4还是在中间添加4 ,或者替换整个选定的单词,或者……),然后使用旧文本触发修改事件*,然后使用(建议的)新文本调用“key”或“all”验证函数,并使用(接受的)新文本更新变量(除非验证函数返回 false,在这种情况下,将调用invalidcommand )。


I don't know which one of those you want, so let's show all of them, and you can play around with them and pick the one you want.我不知道你想要哪一个,所以让我们展示所有这些,你可以和他们一起玩,选择你想要的。

import Tkinter as tk

root = tk.Tk()

def validate(newtext):
    print('validate: {}'.format(newtext))
    return True
vcmd = root.register(validate)

def key(event):
    print('key: {}'.format(event.char))

def var(*args):
    print('var: {} (args {})'.format(svar.get(), args))
svar = tk.StringVar()
svar.trace('w', var)

entry = tk.Entry(root,
                 textvariable=svar, 
                 validate="key", validatecommand=(vcmd, '%P'))
entry.bind('<Key>', key)
entry.pack()
root.mainloop()

The syntax for variable trace callbacks is a bit complicated, and not that well documented in Tkinter;变量跟踪回调的语法有点复杂,并且在 Tkinter 中没有很好的记录; if you want to know what the first two arguments mean, you need to read the Tcl/Tk docs, and understand how Tkinter maps your particular StringVar to the Tcl name 'PY_VAR0' … Really, it's a lot easier to just build a separate function for each variable and mode you want to trace, and ignore the args.如果您想知道前两个参数的含义,您需要阅读 Tcl/Tk 文档,并了解 Tkinter 如何将您的特定StringVar映射到 Tcl 名称'PY_VAR0' ……实际上,构建一个单独的函数要容易'PY_VAR0'对于要跟踪的每个变量和模式,并忽略参数。

The syntax for validation functions is even more complicated, and a lot more flexible than I've shown.验证函数的语法更加复杂,而且比我展示的更加灵活。 For example, you can get the inserted text (which can be more than one character, in case of a paste operation), its position, and all kinds of other things… but none of this is described anywhere in the Tkinter docs, so you will need to go the Tcl/Tk docs .例如,您可以获得插入的文本(在粘贴操作的情况下可以是多个字符)、它的位置以及各种其他内容……但是 Tkinter 文档中没有任何地方描述这些内容,因此您将需要去Tcl/Tk 文档 The most common thing you want is the proposed new text as the argument, and for that, use (vcmd, '%P') .您想要的最常见的事情是建议的新文本作为参数,为此,使用(vcmd, '%P')


Anyway, you should definitely play with doing a variety of different things and see what each mechanism gives you.无论如何,你绝对应该尝试做各种不同的事情,看看每种机制给你带来了什么。 Move the cursor around or select part of the string before typing, paste with the keyboard and with the mouse, drag and drop the selection, hit a variety of special keys, etc.在键入之前移动光标或选择部分字符串,使用键盘和鼠标粘贴,拖放选择,点击各种特殊键等。


* I'm going to ignore this step, because it's different in different versions of Tk, and not very useful anyway. * 我将忽略这一步,因为它在不同版本的 Tk 中有所不同,而且无论如何都不是很有用。 In cases where you really need a modified event, it's probably better to use a Text widget and bind <<Modified>> .如果您确实需要修改事件,最好使用Text小部件并绑定<<Modified>>

If you just need to do simple things without using trace module you can try如果你只需要做简单的事情而不使用跟踪模块,你可以尝试

    def objchangetext(self, textwidget):
        print(textwidget.get())  #print text out to terminal

    text1 = tk.Entry(tk.Tk()) 
    text1.bind("<KeyRelease>", lambda event, arg=(0): objchangetext(text1)) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM