Python 限制Tkinter条目小部件中的值

Python 限制Tkinter条目小部件中的值,python,tkinter,validation,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,tex

我需要将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()
将numpy导入为np
来自Tkinter进口*;
导入tkMessageBox;
第2类:
定义初始化(自,主1):
self.panel2=框架(master1)
self.panel2.grid()
self.button2=按钮(self.panel2,text=“Quit”,command=self.panel2.Quit)
self.button2.grid()
self.text1=条目(self.panel2)
self.text1.grid()
self.text1.bind(“”,self.keybind1)
self.text1.focus()
def keybind1(自身,事件):
如果np.linspace(0,9,10)中的event.int:
打印事件.int
root1=Tk()
窗口2(root1)
root1.mainloop()

我不断收到错误消息,事件实例没有属性“int”。我该怎么办

这使用
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()
参考资料:

  • 说明了
    validate
    validatecommand
    选项。(感谢您的链接)
  • 我学会了如何用Python实现这一点

    • 答案几乎完美,只需添加一点内容即可删除整个字符串。 只有在插入文本时才应检查浮动

      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
      

      我还必须处理一个初始插入案例。这就是我的结局:

          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()
      不声明它会引发异常。

      我不熟悉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
      ,但是
      如果v=“\x08和
      v!=”:“
      语句仍然允许使用backspace、
      (“\x08”)
      和delete、arrow、home、end等键,(这些键具有
      event.char
      ”,”,要正常工作-否则,
      break
      命令会停止在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”)
      ),只需要您将使用的代码

      条目
      小部件返回一个字符串,因此您必须以某种方式提取任何数字,以便将它们与其他字符分开。最简单的方法是使用
      str.isdigit()
      。这是一个内置在python库中的方便的小工具,不需要额外的导入,它将识别从
      条目
      小部件返回的字符串中找到的任何数字(数字)

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

      validate='all'
      允许回调在您
      focusin
      focusout
      或在任何
      键上计算
      p
      的值,从而更改小部件中的内容,因此您不会为误入的字符留下任何漏洞

      总之,让事情变得简单。如果您的回调返回
      True
      ,它将允许输入数据。如果回调返回'False',它将基本上'忽略'键盘输入

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

      编辑:
      这将只考虑盒子中允许的内容。但是,您可以在回调函数中,将
      P
      所具有的任何值添加到所需的任何变量中。

      如果您处理的是以逗号作为小数点的区域设置:

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




      显然,事件对象没有
      int
      属性。谁说的?我试着按照我看不到在这个问题上提到的
      int
      …关于验证的Tk文档可能会有所帮助:感谢链接,schlenk。如何处理删除输入字段中的所有字符?我尝试了
      如果action==0:returntrue
      ,但没有成功。但是,如果我在
      之后选中
      if value\u if_allowed=='':return True
      ,除了ValueError:
      ,它确实允许我删除字段的内容。奇怪。为什么退格删除所有输入的数据在这里不起作用。一个值始终存在,即使在键入值后按backspace键@sunny_old_days:谢谢你的bug报告<当
      value\u if\u allowed
      等于空字符串时,code>float(value\u if\u allowed)
      正在引发
      ValueError
      。我更改了代码以避免出现此
      ValueError
      ,从而允许使用空字符串。感谢您对unutbu答案的修复!他留下了你提到的那种散漫的性格。这是最好的解决办法。谢谢我更喜欢这一个,代码行少一些,所以在我看来更容易理解,谢谢。
      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