views:

91

answers:

2

Hi, When I run this code and focus on choice it is raise a error. I close this message but it is come back again. I want to see only one time this message. How can i do this? What is error in my code ?

Note: I'm sorry for my English. I know it isn't good.

#! -*- coding:utf-8 -*-
import wx

class MyPanel(wx.Panel):
   def __init__(self, parent, *args, **kwargs):
       wx.Panel.__init__(self, parent, *args, **kwargs)
       sizer = wx.BoxSizer(wx.HORIZONTAL)
       self.my_choice = wx.Choice(self, wx.NewId())
       self.my_button = wx.Button(self, wx.NewId(), label = "Procces")
       self.my_button.SetFocus()

       sizer.AddMany([(self.my_choice, 0, wx.ALL, 5),
                      (self.my_button, 0, wx.ALL, 5)])

       self.SetSizer(sizer)
       self.my_choice.Bind(wx.EVT_SET_FOCUS, self.my_choice_on_focus)
       self.my_button.Bind(wx.EVT_BUTTON, self.my_button_on_clicked)

   def my_choice_on_focus(self, evt):
       try:
           self.my_choice.Clear()
           print "Input some items in my_choice"
           raise RuntimeError
       except RuntimeError:
           dlg = wx.MessageDialog(self, "test EVT_SET_FOCUS", "Error", wx.ICON_ERROR|wx.OK )
           dlg.ShowModal()
           dlg.Destroy()
           raise
       evt.Skip()

   def my_button_on_clicked(self, evt):
       print "Procces my choice value"
       evt.Skip()

class MyApp(wx.App):
   def OnInit(self):
       frame = wx.Frame(None, title = "Test")
       panel = MyPanel(frame)
       frame.Show()
       self.SetTopWindow(frame)
       return True

if __name__ == '__main__':
   app = MyApp(redirect = False)
   app.MainLoop()
A: 

The error dialog gets the focus when it is shown. When you close the error dialog, the focus returns to the choice control, firing the event handler again, which pops up the error dialog again, et cetera.

To avoid the event handler from being invoked multiple times, one solution would be to unbind the wx.EVT_SET_FOCUS. Another would be not to bind to wx.EVT_SET_FOCUS at all and do the action that you want to do in my_choice_on_focus somewhere else and/or at another moment in time.

Frank Niessink
A: 

I solved my problem with following code. Thanks to everyone for help.

#! -*- coding:utf-8 -*-
import wx
import wx.lib.evtmgr as em 

class MyPanel(wx.Panel):
    def __init__(self, parent, *args, **kwargs):
        wx.Panel.__init__(self, parent,  *args, **kwargs)
        sizer = wx.BoxSizer(wx.HORIZONTAL)

        self.my_choice = wx.Choice(self, wx.NewId())
        self.my_choice.Append("Make your selection")
        self.my_choice.Select(0)

        self.my_button = wx.Button(self, wx.NewId(), label = "Procces")
        self.my_button.SetFocus()

        sizer.AddMany([(self.my_choice, 0, wx.ALL, 5),
                       (self.my_button, 0, wx.ALL, 5)])

        self.SetSizer(sizer)
        em.eventManager.Register(self.my_choice_set_focus, wx.EVT_SET_FOCUS, self.my_choice)
        em.eventManager.Register(self.my_choice_on_select, wx.EVT_CHOICE, self.my_choice)
        em.eventManager.Register(self.my_button_on_clicked, wx.EVT_BUTTON, self.my_button)


    def my_choice_on_select(self, evt):
        if evt.GetSelection() <= 0:
            print "Procces false selection"
            em.eventManager.Register(self.my_choice_set_focus,
                                     wx.EVT_SET_FOCUS,
                                     self.my_choice)
            self.SetFocusIgnoringChildren()
        else:
            print "Procces true selection"

        evt.Skip()

    def my_choice_set_focus(self, evt):
        try:
            self.my_choice.Clear()
            self.my_choice.Append("Make your selection")
            raise RuntimeError
        except RuntimeError:
            em.eventManager.DeregisterListener(self.my_choice_set_focus)
            dlg = wx.MessageDialog(None, "test EVT_SET_FOCUS", "Error",
                                   wx.ICON_ERROR|wx.OK )
            dlg.ShowModal()
            dlg.Destroy()
            self.my_choice.Clear()
            self.my_choice.Append("Try again...")
            self.my_choice.Select(0)
            evt.Skip()
        evt.Skip()

    def my_button_on_clicked(self, evt):
        print "Procces my choice value"
        evt.Skip()

class MyApp(wx.App):
    def OnInit(self):
        frame = wx.Frame(None, title = "Test")
        panel = MyPanel(frame)
        frame.Show()
        self.SetTopWindow(frame)
        return True

if __name__ == '__main__':
    app = MyApp(redirect = False)
    app.MainLoop()
nozkan