【问题标题】:wxPython validators not working as expectedwxPython 验证器未按预期工作
【发布时间】:2010-09-29 21:30:46
【问题描述】:

我在 wxPtyhon 中编写了一个对话框,其中包含两个组合框,我已将自定义验证器附加到该组合框,目的是确保在键入值时,它是一个数字字符串。问题是,验证器没有被调用。我做错了什么?

    import wx

    # my custom validator class

    class NumericObjectValidator(wx.Validator):
       def __init__(self):
          wx.Validator.__init__(self)

       def Clone(self):
          return NumericObjectValidator()

       # Why isn't this method being called when the user types in the CB field?
       def Validate(self, win):
          cbCtrl = self.GetWindow()
          text = cbCtrl.GetValue()
          print 'control value=',text
          return True

    class SizeDialog(wx.Dialog):
       def __init__(self, parent):
          wx.Dialog.__init__(self, parent, -1, 'Select Size', size=(200,135))

          panel = wx.Panel(self, -1, size=self.GetClientSize())

          sizes = map(str, range(3,21))
          wx.StaticText(panel, -1, 'Rows:', pos=(10, 15))
          self.rows = wx.ComboBox(panel, -1, value='8', choices=sizes,
             style=wx.CB_DROPDOWN, pos=(80,15), validator=NumericObjectValidator())

          wx.StaticText(panel, -1, 'Columns:', pos=(10,40))
          self.cols = wx.ComboBox(panel, -1, choices=sizes, style=wx.CB_DROPDOWN,
             pos=(80,40), value='8', validator=NumericObjectValidator())

          cancel = wx.Button(panel,wx.ID_CANCEL,'Cancel', pos=(20,75))
          wx.Button(panel,wx.ID_OK,'OK', pos=(100,75)).SetDefault()

       def TransferToWindow(self):
          return True

       def TransferFromWindow(self):
          return True

       def get_size(self):
          r = int(self.rows.GetValue())
          c = int(self.cols.GetValue())
          return (c,r)

    if __name__ == "__main__":
       app = wx.App(0)
       dlg = SizeDialog(None)
       dlg.ShowModal()
       dlg.Destroy()

【问题讨论】:

    标签: python wxpython


    【解决方案1】:

    这是 wxWidgets 中的一个怪癖。如果父级不是 wx.Dialog 的(子类),则必须手动调用 wx.Window 上的方法“TransferDataToWindow”和“TransferDataFromWindow”。这里您使用 wx.Panel 作为组合框的父级,因此不会自动调用数据传输。

    【讨论】:

      【解决方案2】:

      我不知道为什么,但是复制 wxPython demo 可以正常工作。

      import wx
      import string
      
      # my custom validator class
      
      class NumericObjectValidator(wx.PyValidator):
          def __init__(self):
              wx.PyValidator.__init__(self)
              self.Bind(wx.EVT_CHAR, self.OnChar)
      
          def Clone(self):
              return NumericObjectValidator()
      
          def Validate(self, win):
              tc = self.GetWindow()
              val = tc.GetValue()
      
              for x in val:
                  if x not in string.digits:
                      return False
      
              return True
      
      
          def OnChar(self, event):
              key = event.GetKeyCode()
      
              if key < wx.WXK_SPACE or key == wx.WXK_DELETE or key > 255:
                  event.Skip()
                  return
      
              if chr(key) in string.digits:
                  event.Skip()
      
              return
      
      
      class SizeDialog(wx.Dialog):
         def __init__(self, parent):
            wx.Dialog.__init__(self, parent, -1, 'Select Size', size=(200,135))
      
            panel = wx.Panel(self, -1, size=self.GetClientSize())
      
            sizes = map(str, range(3,21))
            wx.StaticText(panel, -1, 'Rows:', pos=(10, 15))
            self.rows = wx.ComboBox(panel, -1, value='8', choices=sizes,
               style=wx.CB_DROPDOWN, pos=(80,15), validator=NumericObjectValidator())
      
            wx.StaticText(panel, -1, 'Columns:', pos=(10,40))
            self.cols = wx.ComboBox(panel, -1, style=wx.CB_DROPDOWN, validator=NumericObjectValidator())
      
            cancel = wx.Button(panel,wx.ID_CANCEL,'Cancel', pos=(20,75))
            wx.Button(panel,wx.ID_OK,'OK', pos=(100,75)).SetDefault()
      
         def TransferToWindow(self):
            return True
      
         def TransferFromWindow(self):
            return True
      
         def get_size(self):
            r = int(self.rows.GetValue())
            c = int(self.cols.GetValue())
            return (c,r)
      
      if __name__ == "__main__":
         app = wx.App(0)
         dlg = SizeDialog(None)
         dlg.ShowModal()
         dlg.Destroy()
      

      【讨论】:

      • 我的猜测是因为 OP 使用的是 wx.Validator 而演示使用的是 wx.PyValidator。
      • 其实我都试过了。都不适合我。我现在试试 Steven 的例子,看看是否可行。
      • 我的作品,在 Win XP 上测试。原帖中的那个没有。
      【解决方案3】:
      1. 使用PyValidator 代替Validator
      2. ComboBoxButton 的父级应该是 Dialog 而不是 Panel

      您的代码的以下版本应该可以正常工作:

          import wx
      
          # my custom validator class
      
          class NumericObjectValidator(wx.PyValidator):
      
              def __init__(self):
                  wx.PyValidator.__init__(self)
      
              def Clone(self):
                  return NumericObjectValidator()
      
              # Why isn't this method being called when the user types in the CB
              # field?
              def Validate(self, win):
                  cbCtrl = self.GetWindow()
                  text = cbCtrl.GetValue()
                  print 'control value=', text
                  return True
      
              def TransferToWindow(self):
                  return True
      
              def TransferFromWindow(self):
                  return True
      
          class SizeDialog(wx.Dialog):
      
              def __init__(self, parent):
                  wx.Dialog.__init__(
                      self, parent, -1, 'Select Size', size=(200, 135))
      
                  sizes = map(str, range(3, 21))
                  wx.StaticText(self, -1, 'Rows:', pos=(10, 15))
                  self.rows = wx.ComboBox(self, -1, value='8', choices=sizes,
                                          style=wx.CB_DROPDOWN, pos=(80, 15), validator=NumericObjectValidator())
      
                  wx.StaticText(self, -1, 'Columns:', pos=(10, 40))
                  self.cols = wx.ComboBox(
                      self, -1, choices=sizes, style=wx.CB_DROPDOWN,
                      pos=(80, 40), value='8', validator=NumericObjectValidator())
      
                  cancel = wx.Button(self, wx.ID_CANCEL, 'Cancel', pos=(20, 75))
                  wx.Button(self, wx.ID_OK, 'OK', pos=(100, 75)).SetDefault()
      
              def get_size(self):
                  r = int(self.rows.GetValue())
                  c = int(self.cols.GetValue())
                  return (c, r)
      
          if __name__ == "__main__":
              app = wx.App(0)
              dlg = SizeDialog(None)
              dlg.ShowModal()
              dlg.Destroy()
      

      【讨论】:

        猜你喜欢
        • 2018-03-31
        • 2013-01-21
        • 1970-01-01
        • 1970-01-01
        • 2018-01-27
        • 2012-09-28
        • 1970-01-01
        • 1970-01-01
        • 2018-10-22
        相关资源
        最近更新 更多