zoukankan      html  css  js  c++  java
  • wxPython笔记:TextCtrl 使用验证器

    原文链接

    作者:月小水长

    前言
    TextCtrl 是 wxPython 框架里一个非常实用的文本输入控件,我们经常需要对 TextCtrl 做这样一个输入上的约束:只允许输入数字(比如允许 1.2、4.5、100 这些输入而禁止诸如 .8、4t等输入,方便我们在将输入的 str 类型转成 int、float 等其他类型时不需要额外加判断来防止产生异常。今天我查阅 wxPython 的 API,发现了 Validator 这个类可以满足我们的需求。事实上,不仅是满足只允许输入数字这个需要,掌握了 Validator 这个类的使用,我们可以满足任何定制化的需求。

    编码

    首先必须新建类继承自 wx.Validator

    import wx
    
    class MyNumberValidator(wx.Validator):# 创建验证器子类      
        def __init__(self):
            wx.Validator.__init__(self)
          
        def Clone(self):
            return MyNumberValidator()
    
        def Validate(self,win):#1 使用验证器方法
            return True
    
        def TransferToWindow(self):
            return True
    
        def TransferFromWindow(self):
            return True   

    同时,必须重写 init()(完成初始化)、Clone()(返回当前类的一个实例)等五个方法,你只要把它们当成一个模板就行,然后在此基础上加上我们自己的逻辑。

    根据需求加入实现逻辑

    import wx
    # import wx.lib.imagebrowser
    
    
    class MyNumberValidator(wx.Validator):# 创建验证器子类      
        def __init__(self):
            wx.Validator.__init__(self)
            self.ValidInput = ['.','0','1','2','3','4','5','6','7','8','9']
            self.StringLength = 0
            self.Bind(wx.EVT_CHAR,self.OnCharChanged)  #  绑定字符改变事件
    
        def OnCharChanged(self,event):
            # 得到输入字符的 ASCII 码
            keycode = event.GetKeyCode()
            # 退格(ASCII 码 为8),删除一个字符。
            if keycode == 8:
                self.StringLength -= 1
                #事件继续传递
                event.Skip()
                return
    
            # 把 ASII 码 转成字符
            InputChar = chr(keycode)
    
            if InputChar in self.ValidInput:
                # 第一个字符为 .,非法,拦截该事件,不会成功输入
                if InputChar == '.' and self.StringLength == 0:
                    return False
                # 在允许输入的范围,继续传递该事件。
                else:
                    event.Skip()
                    self.StringLength += 1
                    return True
            return False
    
        def Clone(self):
            return MyNumberValidator()
    
        def Validate(self,win):#1 使用验证器方法
            return True
    
        def TransferToWindow(self):
            return True
    
        def TransferFromWindow(self):
            return True

    注意这行代码,self.Bind(wx.EVT_CHAR,self.OnCharChanged) # 绑定字符输入事件,它的意思是,一旦用户输入了字符,该事件会首先交给OnCharChanged方法处理,在OnCharChanged中,特别注意event.Skip()这行代码,它的意思是,过了合法性检验这一关,该事件可以继续传递了,可以交给将该字符加入 textctrl.value 并显示出来的函数处理;否则,事件就在OnCharChanged中被拦截了,不会显示出来,输入失败。

    给控件 textctrl 绑定验证器子类。
    很简单,只需要在创建 textctrl 的时候加指定关键词参数

    wx.TextCtrl(self,validator=MyNumberValidator(),style=wx.TE_CENTER)

    style=wx.TE_CENTER 使输入字符居中

    再说 Validate() 方法

    我们发现,Validator 类中和类名最相似的方法Validate()一直没有使用,其实这个方法是一般使用流程如下,先在 Validate() 方法中加上业务逻辑。

    def Validate(self,win):#1 使用验证器方法
            print(111)
            textCtrl = self.GetWindow()
            text = textCtrl.GetValue()
            valid_text = ''
            for i in text:
                if i in self.ValidInput:
                    valid_text += i
            textCtrl.SetValue(valid_text)
            return True

    然后在外部调用它验证合法性

    self.n1.GetValidator().Validate(self.n1)

    Validate()也可以验证合法性,只不过它不能处理输入事件,必须在输入完成后才能验证合法性,相当于“马后炮”的作用。

    完整例子:

    # -*- coding: utf-8 -*-
    # author:           inspurer(月小水长)
    # pc_type           lenovo
    # create_time:      2019/4/12 13:37
    # file_name:        validator.py
    # github            https://github.com/inspurer
    # qq邮箱            2391527690@qq.com
    # 微信公众号         月小水长(ID: inspurer)
    
    
    import wx
    # import wx.lib.imagebrowser
    
    
    class MyNumberValidator(wx.Validator):# 创建验证器子类      
        def __init__(self):
            wx.Validator.__init__(self)
            self.ValidInput = ['.','0','1','2','3','4','5','6','7','8','9']
            self.StringLength = 0
            self.Bind(wx.EVT_CHAR,self.OnCharChanged)  #  绑定字符输入事件
    
        def OnCharChanged(self, event):
            # 得到输入字符的 ASCII 码
            keycode = event.GetKeyCode()
            # 退格(ASCII 码 为8),删除一个字符。
            if keycode == 8:
                self.StringLength -= 1
                # 事件继续传递
                event.Skip()
                return
    
            # 把 ASII 码 转成字符
            InputChar = chr(keycode)
    
            if InputChar in self.ValidInput:
                # 第一个字符为 .,非法,拦截该事件,不会成功输入
                if InputChar == '.' and self.StringLength == 0:
                    return False
                # 在允许输入的范围,继续传递该事件。
                else:
                    event.Skip()
                    self.StringLength += 1
                    return True
            return False
    
        def Clone(self):
            return MyNumberValidator()
    
        def Validate(self,win):#1 使用验证器方法
            print(111)
            textCtrl = self.GetWindow()
            text = textCtrl.GetValue()
            valid_text = ''
            for i in text:
                if i in self.ValidInput:
                    valid_text += i
            textCtrl.SetValue(valid_text)
            return True
    
        def TransferToWindow(self):
            return True
    
        def TransferFromWindow(self):
            return True
    
    class GUI(wx.Frame):
        def __init__(self,parent):
            wx.Frame.__init__(self, parent=parent, title="wxPython开发实战",size=(400,300),style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER ^ wx.MAXIMIZE_BOX )
            self.Center()
    
            self.SetBackgroundColour('white')
    
            font = wx.Font(16,wx.DECORATIVE, wx.NORMAL, wx.NORMAL)
            self.n1 = wx.TextCtrl(self,validator=MyNumberValidator(),pos=(100,30),size=(180,45),style=wx.TE_CENTER)
            self.n1.SetFont(font)
            self.n1.SetBackgroundColour('#95ec69')
            self.n1.SetHint('请输入第一个数字')
    
            self.n2 = wx.TextCtrl(self,validator=MyNumberValidator(),pos=(100,100),size=(180,45),style=wx.TE_CENTER)
            self.n2.SetFont(font)
            self.n2.SetBackgroundColour('#95ec69')
            self.n2.SetHint('请输入第二个数字')
    
    
            self.config = wx.Button(self,label="验证输入框一的合法性",pos=(115,170),size=(150,40))
            self.config.SetBackgroundColour('#95ec69')
    
            self.Bind(wx.EVT_BUTTON,self.configClicked,self.config)
    
        def configClicked(self,event):
            self.n1.GetValidator().Validate(self.n1)
            pass
    
    if __name__ == "__main__":
        app = wx.App()
        GUI(None).Show()
        app.MainLoop()
  • 相关阅读:
    BZOJ 2574: [Poi1999]Store-Keeper
    BZOJ 1024: [SCOI2009]生日快乐
    BZOJ 2541: [Ctsc2000]冰原探险
    hihoCoder 1303 数论六·模线性方程组
    Codeforces 710 D. Two Arithmetic Progressions
    BZOJ 1670: [Usaco2006 Oct]Building the Moat护城河的挖掘
    ZJOI2014 2048
    51Nod 1766 树上的最远点对
    Codeforces 727 F. Polycarp's problems
    BZOJ 3736: [Pa2013]Karty
  • 原文地址:https://www.cnblogs.com/-wenli/p/12366377.html
Copyright © 2011-2022 走看看