wx.Validator没有被调用

1 投票
1 回答
773 浏览
提问于 2025-04-17 08:55

我有一个简单的表单,上面有一个多行文本框和确定/取消按钮。我想在点击确定按钮时检查文本框里是否有内容。我试着用 wx.Validator 来实现这个功能,但不知道为什么即使给父窗口加上了额外的样式 wx.WS_EX_VALIDATE_RECURSIVELY,它也从来没有被调用。以下是我的代码:

import wx

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

    def Clone(self):
        return Validator()

    def Validate(self, win):
        txt_ctrl = self.GetWindow()

        if len(txt_ctrl.GetValue()) == 0:
            wx.MessageBox('Please, provide a value.', 'Error')
            txt_ctrl.SetBackgroundColour('pink')
            txt_ctrl.SetFocus()
            txt_ctrl.Refresh()
            return False
        else:
            txt_ctrl.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_WINDOW))
            txt_ctrl.Refresh()
            return True

    def TransferToWindow(self):
        return True

    def TransferFromWindow(self):
        return True

class OkCancelPanel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, wx.ID_ANY)

        self.btn_ok =  wx.Button(self, wx.ID_OK)
        self.btn_cancel = wx.Button(self, wx.ID_CANCEL)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.btn_ok, 0, wx.NORMAL|wx.ALL, 5)
        sizer.Add(self.btn_cancel, 0, wx.NORMAL|wx.ALL, 5)            
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.Layout()

class Panel(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, wx.ID_ANY)

        self.txt = wx.TextCtrl(self, wx.ID_ANY, style = wx.TE_MULTILINE)
        self.okcancel = OkCancelPanel(self)

        sizer_txt = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, 'Some text here'), wx.HORIZONTAL)
        sizer_txt.Add(self.txt, 1, wx.EXPAND, 0)
        sizer_txt.Layout()
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(sizer_txt, 1, wx.EXPAND|wx.ALL, 5)
        sizer.Add(self.okcancel, 0, wx.NORMAL|wx.ALIGN_RIGHT, 0)
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.Layout()

class Frame(wx.Frame):
    def __init__(self, parent):
        wx.Frame.__init__(self, parent, wx.ID_ANY, 'Test Frame', size = (400, 300))
        self.SetSizeHints(minW = 400, minH = 300)

        self.panel = Panel(self)

        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.panel, 1, wx.EXPAND, 0)
        self.SetSizer(sizer)
        sizer.Fit(self)
        self.Layout()

        #--Shortcuts--#
        self.txt = self.panel.txt
        self.btn_ok = self.panel.okcancel.btn_ok
        self.btn_cancel = self.panel.okcancel.btn_cancel

class Controller(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.SetExtraStyle(wx.WS_EX_VALIDATE_RECURSIVELY)   

        self.txt.SetValidator(Validator())     

        self.Bind(wx.EVT_BUTTON, self.OnButton, self.btn_ok )

    def OnButton(self, evt):
        self.txt.Validate()

if __name__ == '__main__':
    app = wx.App()
    frame = Controller(None)
    frame.Show()
    app.SetTopWindow(frame)
    app.MainLoop()

那我到底哪里做错了呢?

当然,我可以在 OnButton 方法里用类似 self.txt.GetValidator().Validate(self.txt) 的方式来检查,但我不想这样 :)

Windows 7 x64, Python 2.7.2, wxPython 2.9.2.4

1 个回答

3

不要使用:

self.txt.Validate()

而是使用:

self.Validate()

撰写回答