【问题标题】:Is it possible to limit TextCtrl to accept numbers only in wxPython?是否可以限制 TextCtrl 仅在 wxPython 中接受数字?
【发布时间】:2009-09-02 17:27:01
【问题描述】:

我想要一个只接受数字的文本控件。 (只是整数值,如 45 或 366)

最好的方法是什么?

【问题讨论】:

    标签: wxpython textctrl


    【解决方案1】:

    我不得不做类似的事情,检查字母数字代码。关于 EVT_CHAR 的提示是正确的:

    class TestPanel(wx.Panel):
        def __init__(self, parent):
            wx.Panel.__init__(self, parent, -1)
            self.entry = wx.TextCtrl(self, -1)
            self.entry.Bind(wx.EVT_CHAR, self.handle_keypress)
    
        def handle_keypress(self, event):
            keycode = event.GetKeyCode()
            if keycode < 255:
                # valid ASCII
                if chr(keycode).isalnum():
                    # Valid alphanumeric character
                    event.Skip()
    

    【讨论】:

    • 当用户按下 del 按钮或箭头按钮时,它将如何工作?
    【解决方案2】:

    IntCtrlMasked Edit ControlNumCtrl 都是专门为此设计的,具有不同的控制级别。查看“更多 Windows/控件”下的 wx 演示,了解它们是如何工作的。

    (或者,如果您真的希望直接使用原始 TextCtrl 执行此操作,我认为您希望捕获 EVT_CHAR 事件,测试字符,并在允许的情况下调用 evt.Skip()字符。)

    【讨论】:

      【解决方案3】:

      您可以尝试IntCtrlEVT_CHAR,或实现一个新的/现有的验证器(如IntValidator)。验证器可用于验证字段(在尝试验证对话框/面板上的多个内容时很有用),它们还可以与 EVT_CHAR 一起使用以限制字段中的输入。

      【讨论】:

        【解决方案4】:

        正如其他答案所指出的,可以使用 EVT_CHAR 处理程序来执行此操作。您需要为要让通过的字符调用event.Skip(),而不是为要阻止的字符调用它。一个细微差别是您可能还想调用event.Skip() 来获取制表符;按下tab会触发EVT_CHAR事件,如果你不调用event.Skip(),你将有效地禁用TextCtrls之间的tab遍历。

        这是一个显示两个TextCtrls 的最小应用程序,它们接受整数或十进制数,并带有工作制表符遍历:

        import wx
        
        app = wx.App()
        
        frame = wx.Frame(None, -1, 'simple.py')
        panel = wx.Panel(frame)
        text_ctrl_1 = wx.TextCtrl(panel, value='123')
        text_ctrl_2 = wx.TextCtrl(panel, value='456', pos=(0, 30))
        
        def block_non_numbers(event):
            key_code = event.GetKeyCode()
        
            # Allow ASCII numerics
            if ord('0') <= key_code <= ord('9'):
                event.Skip()
                return
        
            # Allow decimal points
            if key_code == ord('.'):
                event.Skip()
                return
        
            # Allow tabs, for tab navigation between TextCtrls
            if key_code == ord('\t'):
                event.Skip()
                return
        
            # Block everything else
            return
        
        text_ctrl_1.Bind(wx.EVT_CHAR, block_non_numbers)
        text_ctrl_2.Bind(wx.EVT_CHAR, block_non_numbers)
        
        frame.Show()
        app.MainLoop()
        

        【讨论】:

        • 您可能还需要启用退格、del、左右:if key_code in (8, 127, 314, 316): event.Skip() return 注意,这些值可能取决于平台。
        • @jake77 我相信这些键根本不会触发EVT_CHAR(因此没有必要在EVT_CHAR 处理程序中检查它们),不过我稍后会确认。
        【解决方案5】:

        NumCtrl 对我来说有一些奇怪的怪癖。这是我尝试创建基于 EVT_CHAR 和键码的数字控件。

        此控件允许数字以及所有特殊键码(ctrl 组合键、箭头键、退格键等),因此复制粘贴、撤消重做、全选等仍然有效。它只会阻止其他可打印字符(使用string.printable)和unicode字符(使用WXK_NONE

        另一种检查和允许所有特殊键码的方法可以通过this answer 找到。这是一种更好的方法,但需要更多代码。

        import string
        
        MyNumCtrl = wx.TextCtrl()
        MyNumCtrl.Bind(EVT_CHAR, onChar)
        
        def onChar(self, event):
            keycode = event.GetKeyCode()
            obj = event.GetEventObject()
            val = obj.GetValue()
            # filter unicode characters
            if keycode == wx.WXK_NONE:
                pass 
            # allow digits
            elif chr(keycode) in string.digits:
                event.Skip()
            # allow special, non-printable keycodes
            elif chr(keycode) not in string.printable:
                event.Skip() # allow all other special keycode
            # allow '-' for negative numbers
            elif chr(keycode) == '-':
                if val[0] == '-':
                    obj.SetValue(val[1:])
                else:
                    obj.SetValue('-' + val)
            # allow '.' for float numbers
            elif chr(keycode) == '.' and '.' not in val:
                event.Skip()
            return
        

        【讨论】:

          【解决方案6】:

          我想要相同的,但对于浮动,所以我在类中使用了以下方法:

           def force_numeric(self, event, edit):
              raw_value =  edit.GetValue().strip()
              keycode = event.GetKeyCode()
              if keycode < 255:
                  print('keycode:', keycode,'chr(keycode) ', chr(keycode))
                  if chr(keycode).isdigit() or chr(keycode)=='.' and '.' not in raw_value:
                      print('skip')
                      event.Skip()
          

          在构造函数中注册事件:

              item = wx.TextCtrl(self.panel, -1, str(pose_config['locref_stdev']))
              item.Bind(wx.EVT_CHAR, lambda event: self.force_numeric(event, item))
          

          修改上面的答案

          【讨论】:

            【解决方案7】:

            请检查 wxpython 演示中的“Validator.py”脚本。这正是你所需要的

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2010-09-25
              • 2011-11-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-12-19
              相关资源
              最近更新 更多