限制Tkinter Entry小部件中的值

时间:2012-01-22 08:01:26

标签: python tkinter validation

我需要将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()

我不断收到错误消息,即Event实例没有属性'int'。我该怎么办?

7 个答案:

答案 0 :(得分:15)

这使用validatecommandtk.Entry中的有效用户输入限制为'0123456789.-+'中的字符,并检查输入是否可以解释为浮点数:

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 text in '0123456789.-+':
            try:
                float(value_if_allowed)
                return True
            except ValueError:
                return False
        else:
            return False

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

参考文献:

  • Tk man page解释了validatevalidatecommand 选项。 (感谢schlenk链接)。
  • 我在Python here中学会了如何做到这一点。

答案 1 :(得分:6)

我意识到答案已经很晚了,但我觉得我可以给出更简单的答案......一旦你理解它是如何工作的,这真的很简单。

使用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库中的便捷小工具,无需额外导入,它将识别它从{em>字符串中找到Entry小部件返回的任何数字(数字)。

if语句的or P == ""部分允许您删除整个条目,如果没有它,您将无法删除'%P'返回的最后一个(输入框中的第1个)数字空值并导致回调返回False。我不会在这里详细说明原因。

validate='all'允许回调在Pfocusin或任何focusout笔划上评估key的值,从而更改窗口小部件中的内容因此,您不会为错误输入的杂散字符留下任何漏洞。

总之,要简单化。如果您的回调返回True,则会允许输入数据。如果回调返回'False',它将基本上'忽略'键盘输入。

查看这两个参考文献。他们解释了每个替换代码的含义以及如何实现它们。

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

编辑: 这只会照顾盒子里允许的内容。但是,您可以在回调中将任何值P添加到您希望的任何变量中。

答案 2 :(得分:5)

答案几乎是完美的,只需添加一点就可以删除整个字符串。 只有在插入文本

时才能检查浮动
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

答案 3 :(得分:1)

我还必须处理一个初始插入案例。这就是我最终得到的结果:

    def _checkNumberOnly(self, action, value_if_allowed):
        if action != '1':
           return True
        try:
            return value_if_allowed.isnumeric()
        except ValueError:
           return False

    vcmd = (self.register(self._checkNumberOnly), '%d', '%P')
        self.port = ttk.Entry(self, width=35, validate='key', validatecommand=vcmd)

因此它验证了以下内容:

    self.port.insert(0, '6379')

我不确定是否需要 catch ,因为isnumeric()没有说明它会引发异常。

答案 4 :(得分:0)

我是python和Tkinker的新手,但这最适合我:

    def keybind1 (self,event):
        v = event.char
        try:
            v = int(v)
        except ValueError:
            if v!="\x08" and v!="":
            return "break"

v = int(v)在数字键以外的任何键上触发ValueError,并且 if v!="\x08v!="":"语句仍允许退格,("\x08")和删除,箭头,主页,结尾等键(event.char {{1} }),以正常工作。 ""命令停止将不需要的字符输入到条目框中。

答案 5 :(得分:0)

如果要处理以逗号作为小数点的语言环境:

locale.setlocale(locale.LC_ALL,'de_DE.UTF-8') # German

vcmd = (self.root.register(self.entry_numericonly), '%d', '%P')

self.my_float_entry = tk.Entry(self.root, ... , validate='key', validatecommand=vcmd)

def entry_numericonly(self, action, value_if_allowed):
    if(action == "1"):
        try:
            loc_float  = locale.atof(value_if_allowed)
            loc_float_format = locale.format("%f", loc_float)
            try:
                loc_same_length = loc_float_format[:len(value_if_allowed)]
                return value_if_allowed == loc_same_length
            except:
                return False                    
        except:
            return False
    else:
        return True

答案 6 :(得分:0)

def validate(entry_text):
    chars = '1234567890'
    if any((c not in chars) for c in pin.get()):
        lpin = int(len(pin.get()))-1 
        pin.set(pin.get()[:lpin])

pin.trace("w", lambda *args: validate(pin))