wxPython: Using PyDispatcher instead of Pubsub

The other day, I wrote an updated version of my wxPython pubsub article for wxPython 2.9 and realized I had never gotten around to trying PyDispatcher to see how it differed from pubsub. I'm still not sure how it differs internally, but I thought it would be fun to "port" the pubsub code from the last article to PyDispatcher. Let's see how much changes!

Getting Started

First of all, you will need to go get PyDispatcher and install it on your system. If you have pip installed, you can do the following:

pip install PyDispatcher

Otherwise, go to the project's sourceforge page and download it from there. One of the benefits of using pubsub in wxPython is that it's already included with the standard wxPython distribution. However, if you want to use pubsub OUTSIDE of wxPython, you would have to download its standalone code base and install it too. I just thought I should mention that. Most developers don't like downloading extra packages on top of other packages.

Anyway, now that we have PyDispatcher, let's port the code and see what we end up with!

import wx
from pydispatch import dispatcher 

########################################################################
class OtherFrame(wx.Frame):
    """"""
 
    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, wx.ID_ANY, "Secondary Frame")
        panel = wx.Panel(self)
 
        msg = "Enter a Message to send to the main frame"
        instructions = wx.StaticText(panel, label=msg)
        self.msgTxt = wx.TextCtrl(panel, value="")
        closeBtn = wx.Button(panel, label="Send and Close")
        closeBtn.Bind(wx.EVT_BUTTON, self.onSendAndClose)
 
        sizer = wx.BoxSizer(wx.VERTICAL)
        flags = wx.ALL|wx.CENTER
        sizer.Add(instructions, 0, flags, 5)
        sizer.Add(self.msgTxt, 0, flags, 5)
        sizer.Add(closeBtn, 0, flags, 5)
        panel.SetSizer(sizer)
 
    #----------------------------------------------------------------------
    def onSendAndClose(self, event):
        """
        Send a message and close frame
        """
        msg = self.msgTxt.GetValue()
        dispatcher.send("panelListener", message=msg)
        dispatcher.send("panelListener", message="test2", arg2="2nd argument!")
        self.Close()

########################################################################
class MyPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        
        dispatcher.connect(self.myListener, signal="panelListener",
                           sender=dispatcher.Any)
        
        btn = wx.Button(self, label="Open Frame")
        btn.Bind(wx.EVT_BUTTON, self.onOpenFrame)
        
    #----------------------------------------------------------------------
    def myListener(self, message, arg2=None):
        """
        Listener function
        """
        print "Received the following message: " + message
        if arg2:
            print "Received another arguments: " + str(arg2)
            
    #----------------------------------------------------------------------
    def onOpenFrame(self, event):
        """
        Opens secondary frame
        """
        frame = OtherFrame()
        frame.Show()
    
########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="New PubSub API Tutorial")
        panel = MyPanel(self)
        self.Show()
    
#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

This shouldn't take too long to explain. So we import dispatcher from pydispatch. Then we edit the OtherFrame's onSendAndClose method so it will send messages to our panel listener. How? By doing the following:

dispatcher.send("panelListener", message=msg)
dispatcher.send("panelListener", message="test2", arg2="2nd argument!")

Then in the MyPanel class, we setup a listener like this:

dispatcher.connect(self.myListener, signal="panelListener",
                   sender=dispatcher.Any)

This code tells pydispatcher to listen for any sender that has a signal of panelListener. If it has that signal, then it will call the panel's myListener method. That's all we had to do to port from pubsub to pydispatcher. Wasn't that easy?

Copyright © 2024 Mouse Vs Python | Powered by Pythonlibrary