限制Tkinter Entry小部件中的值

20 投票
10 回答
126225 浏览
提问于 2025-04-17 10:49

我想限制Entry小部件里的输入值只能是数字。我实现的方法是:

import numpy as np
from Tkinter import *;
import tkMessageBox;

class window2:

    def __init__(self,master1):

        self.panel2=Frame(master1)
        self.panel2.grid()

        self.button2=Button(self.panel2,text="Quit",command=self.panel2.quit)
        self.button2.grid()

        self.text1=Entry(self.panel2)
        self.text1.grid()
        self.text1.bind('<KeyPress>', self.keybind1)
        self.text1.focus()

    def keybind1 (self,event):
        if event.int in np.linspace(0,9,10):
            print event.int


root1=Tk()
window2(root1)
root1.mainloop()

但是我一直收到错误信息,说事件实例没有'int'这个属性。我该怎么办呢?

10 个回答

11

这个答案几乎完美,只需要稍微补充一下,以便可以删除整个字符串。在插入文本时,才需要检查浮点数。

def validate_float(self, action, index, value_if_allowed,
    prior_value, text, validation_type, trigger_type, widget_name):
    # action=1 -> insert
    if(action=='1'):
        if text in '0123456789.-+':
            try:
                float(value_if_allowed)
                return True
            except ValueError:
                return False
        else:
            return False
    else:
        return True
30

这个例子使用了 validatecommand 来限制用户在 tk.Entry 输入框中输入的内容,只允许输入可以被理解为浮点数的字符串:

import tkinter as tk

class window2:
    def __init__(self, master1):
        self.panel2 = tk.Frame(master1)
        self.panel2.grid()
        self.button2 = tk.Button(self.panel2, text = "Quit", command = self.panel2.quit)
        self.button2.grid()
        vcmd = (master1.register(self.validate),
                '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
        self.text1 = tk.Entry(self.panel2, validate = 'key', validatecommand = vcmd)
        self.text1.grid()
        self.text1.focus()

    def validate(self, action, index, value_if_allowed,
                       prior_value, text, validation_type, trigger_type, widget_name):
        if value_if_allowed:
            try:
                float(value_if_allowed)
                return True
            except ValueError:
                return False
        else:
            return False

root1 = tk.Tk()
window2(root1)
root1.mainloop()

参考资料:

  • Tk 手册页 解释了 validatevalidatecommand 的选项。(感谢 schlenk 提供的链接)。
  • 我在 这里 学会了如何在 Python 中实现这个功能。
33

我知道这个回答来得有点晚,但我觉得我可以给出一个更简单的解释……其实一旦你明白了它是怎么工作的,就会发现这真的很简单。

使用Entry小部件自带的验证功能。

假设self是一个小部件:

vcmd = (self.register(self.callback))

w = Entry(self, validate='all', validatecommand=(vcmd, '%P')) 
w.pack()

def callback(self, P):
    if str.isdigit(P) or P == "":
        return True
    else:
        return False

你不需要包含所有的替换代码:('%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W'),只需要用到的那些就可以了。

Entry小部件返回的是一个字符串,所以你需要以某种方式提取出数字,以便把它们和其他字符分开。最简单的方法就是使用str.isdigit()。这是一个非常方便的小工具,直接内置在Python的库中,不需要额外导入,它会识别出Entry小部件返回的字符串中的任何数字。

if语句中的or P == ""部分允许你删除整个输入框的内容,如果没有这一部分,你将无法删除最后一个(在输入框中的第一个)数字,因为'%P'会返回一个空值,导致你的回调返回False。这里我就不详细解释了。

validate='all'允许回调在你focusinfocusout或任何key按键时评估P的值,从而确保你不会留下任何空隙,让错误的字符被误输入。

总的来说,为了简单明了。如果你的回调返回True,那么就允许输入数据。如果回调返回False,那么就基本上会“忽略”键盘输入。

可以看看这两个参考资料。它们解释了每个替换代码的含义以及如何使用它们。

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html http://stupidpythonideas.blogspot.ca/2013/12/tkinter-validation.html

编辑: 这只会处理输入框中允许的内容。不过,你可以在回调中将P的值赋给你想要的任何变量。

撰写回答