Search code examples
pythonwxpythonpublish-subscribesubscription

python pubsub subscribe to more than one topic


This may seem a bit general, but the problem is quite simple actually. Is it possible to subscribe to a subset of topics using the pubsub module.

Let me briefly explain what I would like to accomplish. In a wxpython project I want to change the text in the status bar according to different events. So I would like to have one function (one listener) which would subscribe to a set of topics. In the listener I would have if statement and several elif statements where the topic's name would be checked. Then the status bar text would be changed accordingly.

Is it possible to do this, or is it a bad idea in the first place. How should I deal with that kind of situation. Thanks in advance


Solution

  • There are a couple of approaches. First and perhaps simplest, you could have just one listener. When you publish to the listener, you just pass it different pieces of information. For example, from class A, you would pass one string. For class B, you might pass a different string, but to the same listener. Then in the listener, you just check for which string, as you mentioned.

    The other approach would be to create multiple listeners that are all bound to the same function or method. Then you can publish to the different listeners and they will all call the same thing.

    You should use the approach that you find easiest to understand and debug.

    Here's an example:

    import wx
    from wx.lib.pubsub import pub 
    
    ########################################################################
    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="")
    
            sendBtn = wx.Button(panel, label="Send Msg")
            sendBtn.Bind(wx.EVT_BUTTON, self.onSendMsg)
    
            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(sendBtn, 0, flags, 5)
            sizer.Add(closeBtn, 0, flags, 5)
            panel.SetSizer(sizer)
    
        #----------------------------------------------------------------------
        def onSendMsg(self, event):
            """"""
            msg = "Another message!"
            pub.sendMessage("anotherListener", 
                            message=msg,
                            listener="anotherListener")
    
        #----------------------------------------------------------------------
        def onSendAndClose(self, event):
            """
            Send a message and close frame
            """
            msg = self.msgTxt.GetValue()
            pub.sendMessage("panelListener", 
                            message=msg,
                            listener="panelListener")
            self.Close()
    
    ########################################################################
    class MyPanel(wx.Panel):
        """"""
    
        #----------------------------------------------------------------------
        def __init__(self, parent):
            """Constructor"""
            wx.Panel.__init__(self, parent)
            pub.subscribe(self.myListener, "panelListener")
            pub.subscribe(self.myListener, "anotherListener")
    
            btn = wx.Button(self, label="Open Frame")
            btn.Bind(wx.EVT_BUTTON, self.onOpenFrame)
    
        #----------------------------------------------------------------------
        def myListener(self, message, listener=None):
            """
            Listener function
            """
    
            if listener == "panelListener":
                print "panel listener has sent the following: ",
                print message
            elif listener == "anotherListener":
                print "another listener sent the following: ", 
                print message
    
        #----------------------------------------------------------------------
        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 is a modified example from my tutorial: http://www.blog.pythonlibrary.org/2013/09/05/wxpython-2-9-and-the-newer-pubsub-api-a-simple-tutorial/