Creating custom event in WxPython

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • NutJob@gmx.net

    #1

    Creating custom event in WxPython

    Hello,

    I'm faced with the following problem: I have a (secondary) thread that
    monitors a socket for incoming message traffic using the
    select.select() function.

    Besides that I also have the main thread of my WxPython application. So
    far so good.

    Now when my socket thread detects an incoming message, I need my main
    thread to interpret the message and react to it by updating the GUI.
    IMO the best way to achieve this is by having my socket thread send a
    custom event to my application's event loop for the main thread to
    process. However, I'm at a total loss as far as creating custom events
    is concerned. The WxWindows documentation isn't very helpful on this
    either.
    I think I need to derive my own event class from the wxEvent class, but
    I have no idea HOW (i.e. what methods do I need to override, etc.) Can
    anyone help me?

  • Sion Arrowsmith

    #2
    Re: Creating custom event in WxPython

    <NutJob@gmx.net > wrote:[color=blue]
    >Now when my socket thread detects an incoming message, I need my main
    >thread to interpret the message and react to it by updating the GUI.
    >IMO the best way to achieve this is by having my socket thread send a
    >custom event to my application's event loop for the main thread to
    >process. However, I'm at a total loss as far as creating custom events
    >is concerned. The WxWindows documentation isn't very helpful on this
    >either.
    >I think I need to derive my own event class from the wxEvent class, but
    >I have no idea HOW (i.e. what methods do I need to override, etc.) Can
    >anyone help me?[/color]

    (a) Consider whether you can do what you want with CallAfter().

    (b) If you do have to go with a custom event, the idiom I've got here
    is:

    EVT_CUSTOM_WITH _DATA_ID = wxNewId()

    def EVT_CUSTOM_WITH _DATA(win, func):
    win.Connect(-1, -1, EVT_CUSTOM_WITH _DATA_ID, func)

    class CustomWithDataE vent(wxPyEvent) :
    def __init__(self, data=None):
    wxPyEvent.__ini t__(self)
    self.data = data
    self.SetEventTy pe(EVT_CUSTOM_W ITH_DATA_ID)

    def Clone(self):
    return CustomWithDataE vent(self.data)

    but do note that this is for wxPython2.4 -- amongst other differences,
    EVT_CUSTOM_WITH _DATA() should be unnecessary in 2.6 (used Bind()
    instead).

    --
    \S -- siona@chiark.gr eenend.org.uk -- http://www.chaos.org.uk/~sion/
    ___ | "Frankly I have no feelings towards penguins one way or the other"
    \X/ | -- Arthur C. Clarke
    her nu becomeþ se bera eadward ofdun hlæddre heafdes bæce bump bump bump

    Comment

    • fraca7

      #3
      Re: Creating custom event in WxPython

      NutJob@gmx.net a écrit :
      [color=blue]
      > Now when my socket thread detects an incoming message, I need my main
      > thread to interpret the message and react to it by updating the GUI.
      > IMO the best way to achieve this is by having my socket thread send a
      > custom event to my application's event loop for the main thread to
      > process. However, I'm at a total loss as far as creating custom events
      > is concerned. The WxWindows documentation isn't very helpful on this
      > either.[/color]

      I think this is what you're looking for:

      # begin code

      import wx

      wxEVT_INVOKE = wx.NewEventType ()

      class InvokeEvent(wx. PyEvent):
      def __init__(self, func, args, kwargs):
      wx.PyEvent.__in it__(self)
      self.SetEventTy pe(wxEVT_INVOKE )
      self.__func = func
      self.__args = args
      self.__kwargs = kwargs

      def invoke(self):
      self.__func(*se lf.__args, **self.__kwargs )

      class MyFrame(wx.Fram e):
      def __init__(self, *args, **kwargs):
      wx.Frame.__init __(self, *args, **kwargs)
      self.Connect(-1, -1, wxEVT_INVOKE, self.onInvoke)

      def onInvoke(self, evt):
      evt.invoke()

      def invokeLater(sel f, func, *args, **kwargs):
      self.GetEventHa ndler().AddPend ingEvent(Invoke Event(func, args,
      kwargs))

      # end code

      This way, if frm is an instance of MyFrame, invoking
      frm.invokeLater (somecallable, arguments...) will invoke 'somecallable'
      with the specified arguments in the main GUI thread.

      I found this idiom somewhere on the Web and can't remember where.

      HTH

      Comment

      • NutJob@gmx.net

        #4
        Re: Creating custom event in WxPython

        Cool, thanks a bunch!

        Comment

        • Chris Lambacher

          #5
          Re: Creating custom event in WxPython

          You should be derriving from PyCommandEvent since only CommandEvents are set
          to propegate, which is probably what you want (see the wxwidgets Event
          handling overview).

          In order to use Bind you will need an instance of PyEventBinder. For the
          example below that would be something like:

          EVT_INVOKE = PyEventBinder(w xEVT_INVOKE)

          -Chris


          On Thu, Sep 01, 2005 at 04:25:05PM +0200, fraca7 wrote:[color=blue]
          > NutJob@gmx.net a ?crit :
          >[color=green]
          > > Now when my socket thread detects an incoming message, I need my main
          > > thread to interpret the message and react to it by updating the GUI.
          > > IMO the best way to achieve this is by having my socket thread send a
          > > custom event to my application's event loop for the main thread to
          > > process. However, I'm at a total loss as far as creating custom events
          > > is concerned. The WxWindows documentation isn't very helpful on this
          > > either.[/color]
          >
          > I think this is what you're looking for:
          >
          > # begin code
          >
          > import wx
          >
          > wxEVT_INVOKE = wx.NewEventType ()
          >
          > class InvokeEvent(wx. PyEvent):
          > def __init__(self, func, args, kwargs):
          > wx.PyEvent.__in it__(self)
          > self.SetEventTy pe(wxEVT_INVOKE )
          > self.__func = func
          > self.__args = args
          > self.__kwargs = kwargs
          >
          > def invoke(self):
          > self.__func(*se lf.__args, **self.__kwargs )
          >
          > class MyFrame(wx.Fram e):
          > def __init__(self, *args, **kwargs):
          > wx.Frame.__init __(self, *args, **kwargs)
          > self.Connect(-1, -1, wxEVT_INVOKE, self.onInvoke)
          >
          > def onInvoke(self, evt):
          > evt.invoke()
          >
          > def invokeLater(sel f, func, *args, **kwargs):
          > self.GetEventHa ndler().AddPend ingEvent(Invoke Event(func, args,
          > kwargs))
          >
          > # end code
          >
          > This way, if frm is an instance of MyFrame, invoking
          > frm.invokeLater (somecallable, arguments...) will invoke 'somecallable'
          > with the specified arguments in the main GUI thread.
          >
          > I found this idiom somewhere on the Web and can't remember where.
          >
          > HTH
          > --
          > http://mail.python.org/mailman/listinfo/python-list[/color]

          Comment

          Working...