Question on MVC and multiple wx.Panels

From: Marco De Felice <m.defel@gmail.com>

Any help would be appreciated! Would it make sense to

pass a reference to

the top level wx.Frame to all panels displayed on the

BasePanel?
To get acces to the top level frame from anywhere a wx
import is present I usually do a wx.GetApp().GetTopWindow()

I wouldn't do that -- that is building into the Panel that the frame it needs to work with is the TopWindow -- it may well be now, but who knows in the future -- for that matter, it may not even be a frame after refactoring.

If you need to work with the frame, then, yes, I'd pass a reference in to the panels. However, the great thing about pubsub is that you don't need to know about the other widgets, you simply publish a "this has happened" message, and anything that need to do something as a response will get it.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@noaa.gov

I wouldn’t do that – that is building into the Panel that the frame it

needs to work with is the TopWindow – it may well be now, but who knows

in the future – for that matter, it may not even be a frame after

refactoring.

If you need to work with the frame, then, yes, I’d pass a reference in

to the panels. However, the great thing about pubsub is that you don’t

need to know about the other widgets, you simply publish a "this has

happened" message, and anything that need to do something as a response

will get it.

-Chris

Christopher Barker, Ph.D.

Oceanographer

Emergency Response Division

NOAA/NOS/OR&R (206) 526-6959 voice

7600 Sand Point Way NE (206) 526-6329 fax

Seattle, WA 98115 (206) 526-6317 main reception

Remember also that the data portion of a message can contain anything. I frequently publish messages with a topic that says “this interesting thing happened” and the data portion being a dictionary of important stuff; things like “the wx tree item that was clicked” or “the panel that originated the message” or “a method that will retrieve important data”. There always needs to be a contract between publishers and subscribers about message content, so give it some thought and I am sure you can devise a reasonable approach.

Christopher Barker ha scritto:

From: Marco De Felice <m.defel@gmail.com>

Any help would be appreciated! Would it make sense to

pass a reference to

the top level wx.Frame to all panels displayed on the

BasePanel?
To get acces to the top level frame from anywhere a wx
import is present I usually do a wx.GetApp().GetTopWindow()

I wouldn't do that -- that is building into the Panel that the frame it needs to work with is the TopWindow -- it may well be now, but who knows in the future -- for that matter, it may not even be a frame after refactoring.

You are right, in fact I use the gettopwindow only to pass a parent to modal message boxes.
Anyway I think the mvc/whatever refactoring is really a hard step for a wxpython user, it has been a real struggle for me.
Someone should start a project for a mvc/whatever framework!

Yes, I found it discouragingly difficult to take an app that was working
fine but was not structured in any specific way and refactor it into
MVC--I gave up in fact, and am much happier (for now at least) with
the structure I do have, which puts functions that are relevant to the
GUI elements right in the classes with them (and no need for worry
about inter-class communication).

I imagine MVC is easier to start from scratch.

···

On Fri, Oct 9, 2009 at 10:51 AM, Marco De Felice <m.defel@gmail.com> wrote:

Christopher Barker ha scritto:

From: Marco De Felice <m.defel@gmail.com>

Any help would be appreciated! Would it make sense to

pass a reference to

the top level wx.Frame to all panels displayed on the

BasePanel?
To get acces to the top level frame from anywhere a wx
import is present
I usually do a wx.GetApp().GetTopWindow()

I wouldn't do that -- that is building into the Panel that the frame it
needs to work with is the TopWindow -- it may well be now, but who knows
in the future -- for that matter, it may not even be a frame after
refactoring.

You are right, in fact I use the gettopwindow only to pass a parent to
modal message boxes.
Anyway I think the mvc/whatever refactoring is really a hard step for a
wxpython user, it has been a real struggle for me.
Someone should start a project for a mvc/whatever framework!

Is it because your topic is "panel.changed" when you send the msg, but
("panel.changed") when you subscribe?

···

On Fri, Oct 9, 2009 at 2:52 PM, David LePage <dwlepage@yahoo.com> wrote:

Thanks guys, this has been helpful, and i'm glad i'm not the only one who finds this a difficult task..

If you dont mind, I have one additional q, i'm hoping someone can point out my problem.. I can't seem to get my pubsub messages in the controller for some reason.. I put together a short sample program that illustrates this. Can someone find my error?

class DataCollectorModel:
def __init__(self):
self.junk = [2500]

def add(self, value):
self.junk.append(value)
print "Added: %s" % value

class Controller:
def __init__(self, app):
Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))
self.model = DataCollectorModel()
self.view = View(None)
self.view.Show()

def __panelChangeListener(self, message):
print "*****Panel changed!"

class View(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, 'My Application',
style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX), size=(697,575))
self.CenterOnScreen()
self.basepanel = BasePanel(self)
self.Fit()

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

def __do_layout(self):
#top level vertical sizer
vmainbox = wx.BoxSizer(wx.VERTICAL)
next = wx.Button(self, wx.ID_ANY, "Next")
vmainbox.Add(next, 0, wx.ALL)
#Bind listener
self.Bind(wx.EVT_BUTTON, self.OnNextClick, next)
self.Fit()

def OnNextClick(self, evt):
Publisher().sendMessage("panel.changed", "Test")

if __name__ =='__main__':
app = wx.PySimpleApp()
Controller(app)
app.MainLoop()

thanks!

I noticed that too, but fixing it didn't solve the issue...I tried
sticking the subscribe line and it's method into the wx.Frame instead,
and it worked there...but I think that probably defeats the purpose.

···

On Oct 9, 2:31 pm, C M <cmpyt...@gmail.com> wrote:

On Fri, Oct 9, 2009 at 2:52 PM, David LePage <dwlep...@yahoo.com> wrote:

> Thanks guys, this has been helpful, and i'm glad i'm not the only one who finds this a difficult task..

> If you dont mind, I have one additional q, i'm hoping someone can point out my problem.. I can't seem to get my pubsub messages in the controller for some reason.. I put together a short sample program that illustrates this. Can someone find my error?

> class DataCollectorModel:
> def __init__(self):
> self.junk = [2500]

> def add(self, value):
> self.junk.append(value)
> print "Added: %s" % value

> class Controller:
> def __init__(self, app):
> Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))
> self.model = DataCollectorModel()
> self.view = View(None)
> self.view.Show()

> def __panelChangeListener(self, message):
> print "*****Panel changed!"

> class View(wx.Frame):
> def __init__(self, parent):
> wx.Frame.__init__(self, parent, -1, 'My Application',
> style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX), size=(697,575))
> self.CenterOnScreen()
> self.basepanel = BasePanel(self)
> self.Fit()

> class BasePanel(wx.Panel):
> def __init__(self, parent):
> wx.Panel.__init__(self, parent, wx.ID_ANY)
> self.parent = parent
> self.__do_layout()

> def __do_layout(self):
> #top level vertical sizer
> vmainbox = wx.BoxSizer(wx.VERTICAL)
> next = wx.Button(self, wx.ID_ANY, "Next")
> vmainbox.Add(next, 0, wx.ALL)
> #Bind listener
> self.Bind(wx.EVT_BUTTON, self.OnNextClick, next)
> self.Fit()

> def OnNextClick(self, evt):
> Publisher().sendMessage("panel.changed", "Test")

> if __name__ =='__main__':
> app = wx.PySimpleApp()
> Controller(app)
> app.MainLoop()

> thanks!

Is it because your topic is "panel.changed" when you send the msg, but
("panel.changed") when you subscribe?

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

I cannot see the problem even with having run this code (with the needed
imports). It's bugging me--can anyone explain why this doesn't work?

Che

···

On Fri, Oct 9, 2009 at 3:55 PM, Mike Driscoll <kyosohma@gmail.com> wrote:

On Oct 9, 2:31 pm, C M <cmpyt...@gmail.com> wrote:

On Fri, Oct 9, 2009 at 2:52 PM, David LePage <dwlep...@yahoo.com> wrote:

> Thanks guys, this has been helpful, and i'm glad i'm not the only one who finds this a difficult task..

> If you dont mind, I have one additional q, i'm hoping someone can point out my problem.. I can't seem to get my pubsub messages in the controller for some reason.. I put together a short sample program that illustrates this. Can someone find my error?

> class DataCollectorModel:
> def __init__(self):
> self.junk = [2500]

> def add(self, value):
> self.junk.append(value)
> print "Added: %s" % value

> class Controller:
> def __init__(self, app):
> Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))
> self.model = DataCollectorModel()
> self.view = View(None)
> self.view.Show()

> def __panelChangeListener(self, message):
> print "*****Panel changed!"

> class View(wx.Frame):
> def __init__(self, parent):
> wx.Frame.__init__(self, parent, -1, 'My Application',
> style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX), size=(697,575))
> self.CenterOnScreen()
> self.basepanel = BasePanel(self)
> self.Fit()

> class BasePanel(wx.Panel):
> def __init__(self, parent):
> wx.Panel.__init__(self, parent, wx.ID_ANY)
> self.parent = parent
> self.__do_layout()

> def __do_layout(self):
> #top level vertical sizer
> vmainbox = wx.BoxSizer(wx.VERTICAL)
> next = wx.Button(self, wx.ID_ANY, "Next")
> vmainbox.Add(next, 0, wx.ALL)
> #Bind listener
> self.Bind(wx.EVT_BUTTON, self.OnNextClick, next)
> self.Fit()

> def OnNextClick(self, evt):
> Publisher().sendMessage("panel.changed", "Test")

> if __name__ =='__main__':
> app = wx.PySimpleApp()
> Controller(app)
> app.MainLoop()

> thanks!

Is it because your topic is "panel.changed" when you send the msg, but
("panel.changed") when you subscribe?

I noticed that too, but fixing it didn't solve the issue...I tried
sticking the subscribe line and it's method into the wx.Frame instead,
and it worked there...but I think that probably defeats the purpose.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

C M ha scritto:

Thanks guys, this has been helpful, and i'm glad i'm not the only one who finds this a difficult task..
If you dont mind, I have one additional q, i'm hoping someone can point out my problem.. I can't seem to get my pubsub messages in the controller for some reason.. I put together a short sample program that illustrates this. Can someone find my error?
class DataCollectorModel:
def __init__(self):
   self.junk = [2500]
def add(self, value):
   self.junk.append(value)
   print "Added: %s" % value
class Controller:
def __init__(self, app):
   Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))
   self.model = DataCollectorModel()
   self.view = View(None)
   self.view.Show()
def __panelChangeListener(self, message):
   print "*****Panel changed!"
class View(wx.Frame):
def __init__(self, parent):
   wx.Frame.__init__(self, parent, -1, 'My Application',
                     style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX), size=(697,575))
   self.CenterOnScreen()
   self.basepanel = BasePanel(self)
   self.Fit()
class BasePanel(wx.Panel):
def __init__(self, parent):
   wx.Panel.__init__(self, parent, wx.ID_ANY)
   self.parent = parent
   self.__do_layout()
def __do_layout(self):
   #top level vertical sizer
   vmainbox = wx.BoxSizer(wx.VERTICAL)
   next = wx.Button(self, wx.ID_ANY, "Next")
   vmainbox.Add(next, 0, wx.ALL)
   #Bind listener
   self.Bind(wx.EVT_BUTTON, self.OnNextClick, next)
   self.Fit()
def OnNextClick(self, evt):
   Publisher().sendMessage("panel.changed", "Test")
if __name__ =='__main__':
app = wx.PySimpleApp()
Controller(app)
app.MainLoop()
thanks!

Is it because your topic is "panel.changed" when you send the msg, but
("panel.changed") when you subscribe?

I noticed that too, but fixing it didn't solve the issue...I tried
sticking the subscribe line and it's method into the wx.Frame instead,
and it worked there...but I think that probably defeats the purpose.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

I cannot see the problem even with having run this code (with the needed
imports). It's bugging me--can anyone explain why this doesn't work?

I don't know the internals, but putting the subscription outside the Controller.__init__ works (perhaps some window is not completely initialized inside the Controller.__init__()???) like the following:

class Controller:
   def __init__(self, app):
     self.model = DataCollectorModel()
     self.view = View(None)
     self.view.Show()
  
   def postinit(self):
  pubsub.Publisher().subscribe(self.__panelChangeListener, "panel.changed")
  
if __name__ =='__main__':
   app = wx.PySimpleApp()
   c = Controller(app)
   c.postinit()
   app.MainLoop()

···

On Fri, Oct 9, 2009 at 3:55 PM, Mike Driscoll <kyosohma@gmail.com> wrote:

On Oct 9, 2:31 pm, C M <cmpyt...@gmail.com> wrote:

On Fri, Oct 9, 2009 at 2:52 PM, David LePage <dwlep...@yahoo.com> wrote:

Marco De Felice wrote:

C M ha scritto:
  

Thanks guys, this has been helpful, and i'm glad i'm not the only one who finds this a difficult task..
If you dont mind, I have one additional q, i'm hoping someone can point out my problem.. I can't seem to get my pubsub messages in the controller for some reason.. I put together a short sample program that illustrates this. Can someone find my error?
class DataCollectorModel:
def __init__(self):
   self.junk = [2500]
def add(self, value):
   self.junk.append(value)
   print "Added: %s" % value
class Controller:
def __init__(self, app):
   Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))
   self.model = DataCollectorModel()
   self.view = View(None)
   self.view.Show()
def __panelChangeListener(self, message):
   print "*****Panel changed!"
class View(wx.Frame):
def __init__(self, parent):
   wx.Frame.__init__(self, parent, -1, 'My Application',
                     style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX), size=(697,575))
   self.CenterOnScreen()
   self.basepanel = BasePanel(self)
   self.Fit()
class BasePanel(wx.Panel):
def __init__(self, parent):
   wx.Panel.__init__(self, parent, wx.ID_ANY)
   self.parent = parent
   self.__do_layout()
def __do_layout(self):
   #top level vertical sizer
   vmainbox = wx.BoxSizer(wx.VERTICAL)
   next = wx.Button(self, wx.ID_ANY, "Next")
   vmainbox.Add(next, 0, wx.ALL)
   #Bind listener
   self.Bind(wx.EVT_BUTTON, self.OnNextClick, next)
   self.Fit()
def OnNextClick(self, evt):
   Publisher().sendMessage("panel.changed", "Test")
if __name__ =='__main__':
app = wx.PySimpleApp()
Controller(app)
app.MainLoop()
thanks!
          

Is it because your topic is "panel.changed" when you send the msg, but
("panel.changed") when you subscribe?
        

I noticed that too, but fixing it didn't solve the issue...I tried
sticking the subscribe line and it's method into the wx.Frame instead,
and it worked there...but I think that probably defeats the purpose.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

I cannot see the problem even with having run this code (with the needed
imports). It's bugging me--can anyone explain why this doesn't work?

I don't know the internals, but putting the subscription outside the
Controller.__init__ works (perhaps some window is not completely
initialized inside the Controller.__init__()???) like the following:

class Controller:
   def __init__(self, app):
     self.model = DataCollectorModel()
     self.view = View(None)
     self.view.Show()
  
   def postinit(self):
  pubsub.Publisher().subscribe(self.__panelChangeListener,
"panel.changed")
  
if __name__ =='__main__':
   app = wx.PySimpleApp()
   c = Controller(app)
   c.postinit()
   app.MainLoop()
  

This really intrigued me.

Seeing Marcos solution pointed me in the right way.

At the end the only thing needed to be changed was.

Controller(app)

change to:

c = Controller(app)

I can only guess that if you don't keep a reference the controller is
initialized and immediately destroyed.

Werner

···

On Fri, Oct 9, 2009 at 3:55 PM, Mike Driscoll <kyosohma@gmail.com> wrote:

On Oct 9, 2:31 pm, C M <cmpyt...@gmail.com> wrote:

On Fri, Oct 9, 2009 at 2:52 PM, David LePage <dwlep...@yahoo.com> wrote:

>

As I understand it, Classes are basically just directions for creating
an object. If you don't provide a variable (i.e. object name) for the
object to reside in, Python should just clean it up immediately.

···

On Oct 12, 4:03 am, werner <wbru...@free.fr> wrote:

Marco De Felice wrote:
> C M ha scritto:

>> On Fri, Oct 9, 2009 at 3:55 PM, Mike Driscoll <kyoso...@gmail.com> wrote:

>>> On Oct 9, 2:31 pm, C M <cmpyt...@gmail.com> wrote:

>>>> On Fri, Oct 9, 2009 at 2:52 PM, David LePage <dwlep...@yahoo.com> wrote:

>>>>> Thanks guys, this has been helpful, and i'm glad i'm not the only one who finds this a difficult task..
>>>>> If you dont mind, I have one additional q, i'm hoping someone can point out my problem.. I can't seem to get my pubsub messages in the controller for some reason.. I put together a short sample program that illustrates this. Can someone find my error?
>>>>> class DataCollectorModel:
>>>>> def __init__(self):
>>>>> self.junk = [2500]
>>>>> def add(self, value):
>>>>> self.junk.append(value)
>>>>> print "Added: %s" % value
>>>>> class Controller:
>>>>> def __init__(self, app):
>>>>> Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))
>>>>> self.model = DataCollectorModel()
>>>>> self.view = View(None)
>>>>> self.view.Show()
>>>>> def __panelChangeListener(self, message):
>>>>> print "*****Panel changed!"
>>>>> class View(wx.Frame):
>>>>> def __init__(self, parent):
>>>>> wx.Frame.__init__(self, parent, -1, 'My Application',
>>>>> style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX), size=(697,575))
>>>>> self.CenterOnScreen()
>>>>> self.basepanel = BasePanel(self)
>>>>> self.Fit()
>>>>> class BasePanel(wx.Panel):
>>>>> def __init__(self, parent):
>>>>> wx.Panel.__init__(self, parent, wx.ID_ANY)
>>>>> self.parent = parent
>>>>> self.__do_layout()
>>>>> def __do_layout(self):
>>>>> #top level vertical sizer
>>>>> vmainbox = wx.BoxSizer(wx.VERTICAL)
>>>>> next = wx.Button(self, wx.ID_ANY, "Next")
>>>>> vmainbox.Add(next, 0, wx.ALL)
>>>>> #Bind listener
>>>>> self.Bind(wx.EVT_BUTTON, self.OnNextClick, next)
>>>>> self.Fit()
>>>>> def OnNextClick(self, evt):
>>>>> Publisher().sendMessage("panel.changed", "Test")
>>>>> if __name__ =='__main__':
>>>>> app = wx.PySimpleApp()
>>>>> Controller(app)
>>>>> app.MainLoop()
>>>>> thanks!

>>>> Is it because your topic is "panel.changed" when you send the msg, but
>>>> ("panel.changed") when you subscribe?

>>> I noticed that too, but fixing it didn't solve the issue...I tried
>>> sticking the subscribe line and it's method into the wx.Frame instead,
>>> and it worked there...but I think that probably defeats the purpose.

>>> -------------------
>>> Mike Driscoll

>>> Blog: http://blog.pythonlibrary.org

>> I cannot see the problem even with having run this code (with the needed
>> imports). It's bugging me--can anyone explain why this doesn't work?

> I don't know the internals, but putting the subscription outside the
> Controller.__init__ works (perhaps some window is not completely
> initialized inside the Controller.__init__()???) like the following:

> class Controller:
> def __init__(self, app):
> self.model = DataCollectorModel()
> self.view = View(None)
> self.view.Show()

> def postinit(self):
> pubsub.Publisher().subscribe(self.__panelChangeListener,
> "panel.changed")

> if __name__ =='__main__':
> app = wx.PySimpleApp()
> c = Controller(app)
> c.postinit()
> app.MainLoop()

This really intrigued me.

Seeing Marcos solution pointed me in the right way.

At the end the only thing needed to be changed was.

Controller(app)

change to:

c = Controller(app)

I can only guess that if you don't keep a reference the controller is
initialized and immediately destroyed.

Werner

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

Nice job hunting this down, Marco, Werner, and Mike. I was focusing
on the pubsub syntax itself and couldn't figure out why it wouldn't work,
as that part was fine, it seemed.

My remaining questions is now, in reference to Mike's point: why
does the Publisher class *not* need to put "stored" in a reference?
In other words, one can set up a listener:

   Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))

which is calling the class ( Publisher() ), without assigning it into a
reference--yet that listener persists. Why is this?

Thanks,
Che

···

On Mon, Oct 12, 2009 at 11:18 AM, Mike Driscoll <kyosohma@gmail.com> wrote:

On Oct 12, 4:03 am, werner <wbru...@free.fr> wrote:

Marco De Felice wrote:
> C M ha scritto:

>> On Fri, Oct 9, 2009 at 3:55 PM, Mike Driscoll <kyoso...@gmail.com> wrote:

>>> On Oct 9, 2:31 pm, C M <cmpyt...@gmail.com> wrote:

>>>> On Fri, Oct 9, 2009 at 2:52 PM, David LePage <dwlep...@yahoo.com> wrote:

>>>>> Thanks guys, this has been helpful, and i'm glad i'm not the only one who finds this a difficult task..
>>>>> If you dont mind, I have one additional q, i'm hoping someone can point out my problem.. I can't seem to get my pubsub messages in the controller for some reason.. I put together a short sample program that illustrates this. Can someone find my error?
>>>>> class DataCollectorModel:
>>>>> def __init__(self):
>>>>> self.junk = [2500]
>>>>> def add(self, value):
>>>>> self.junk.append(value)
>>>>> print "Added: %s" % value
>>>>> class Controller:
>>>>> def __init__(self, app):
>>>>> Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))
>>>>> self.model = DataCollectorModel()
>>>>> self.view = View(None)
>>>>> self.view.Show()
>>>>> def __panelChangeListener(self, message):
>>>>> print "*****Panel changed!"
>>>>> class View(wx.Frame):
>>>>> def __init__(self, parent):
>>>>> wx.Frame.__init__(self, parent, -1, 'My Application',
>>>>> style=wx.DEFAULT_FRAME_STYLE ^ (wx.RESIZE_BORDER | wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX), size=(697,575))
>>>>> self.CenterOnScreen()
>>>>> self.basepanel = BasePanel(self)
>>>>> self.Fit()
>>>>> class BasePanel(wx.Panel):
>>>>> def __init__(self, parent):
>>>>> wx.Panel.__init__(self, parent, wx.ID_ANY)
>>>>> self.parent = parent
>>>>> self.__do_layout()
>>>>> def __do_layout(self):
>>>>> #top level vertical sizer
>>>>> vmainbox = wx.BoxSizer(wx.VERTICAL)
>>>>> next = wx.Button(self, wx.ID_ANY, "Next")
>>>>> vmainbox.Add(next, 0, wx.ALL)
>>>>> #Bind listener
>>>>> self.Bind(wx.EVT_BUTTON, self.OnNextClick, next)
>>>>> self.Fit()
>>>>> def OnNextClick(self, evt):
>>>>> Publisher().sendMessage("panel.changed", "Test")
>>>>> if __name__ =='__main__':
>>>>> app = wx.PySimpleApp()
>>>>> Controller(app)
>>>>> app.MainLoop()
>>>>> thanks!

>>>> Is it because your topic is "panel.changed" when you send the msg, but
>>>> ("panel.changed") when you subscribe?

>>> I noticed that too, but fixing it didn't solve the issue...I tried
>>> sticking the subscribe line and it's method into the wx.Frame instead,
>>> and it worked there...but I think that probably defeats the purpose.

>>> -------------------
>>> Mike Driscoll

>>> Blog: http://blog.pythonlibrary.org

>> I cannot see the problem even with having run this code (with the needed
>> imports). It's bugging me--can anyone explain why this doesn't work?

> I don't know the internals, but putting the subscription outside the
> Controller.__init__ works (perhaps some window is not completely
> initialized inside the Controller.__init__()???) like the following:

> class Controller:
> def __init__(self, app):
> self.model = DataCollectorModel()
> self.view = View(None)
> self.view.Show()

> def postinit(self):
> pubsub.Publisher().subscribe(self.__panelChangeListener,
> "panel.changed")

> if __name__ =='__main__':
> app = wx.PySimpleApp()
> c = Controller(app)
> c.postinit()
> app.MainLoop()

This really intrigued me.

Seeing Marcos solution pointed me in the right way.

At the end the only thing needed to be changed was.

Controller(app)

change to:

c = Controller(app)

I can only guess that if you don't keep a reference the controller is
initialized and immediately destroyed.

Werner

As I understand it, Classes are basically just directions for creating
an object. If you don't provide a variable (i.e. object name) for the
object to reside in, Python should just clean it up immediately.

-------------------
Mike Driscoll

Blog: http://blog.pythonlibrary.org

Che,

C M wrote:

  

...

Nice job hunting this down, Marco, Werner, and Mike. I was focusing
on the pubsub syntax itself and couldn't figure out why it wouldn't work,
as that part was fine, it seemed.

My remaining questions is now, in reference to Mike's point: why
does the Publisher class *not* need to put "stored" in a reference?
In other words, one can set up a listener:

   Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))

which is calling the class ( Publisher() ), without assigning it into a
reference--yet that listener persists. Why is this?
  

It is instantiated in the module itself.

Have a look around line 835 in wx.lib.pubsub (wx version 2.8.10.1).

Publisher is implemented using a pattern called Singleton (Singleton pattern - Wikipedia).

You might also want to have a look at the new version on sourceforge (http://pubsub.sourceforge.net/ and http://groups.google.com/group/pypubsub). I especially like the new documentation stuff one can do (see the attached sample file from v3 svn), i.e. one will be able to document the publisher/listener's and has also better ways in enforcing things. Even if you use strings for your messages you can configure it to get an exception if you try to send a message which is not defined.

Recently played a bit with it as I wanted to learn how to do hierarchies. If you want to look at it you should probably use the SVN version at least when I tried it a couple of weeks ago they were a bit out of date.

Werner

ex3b_main.py (3.05 KB)

···

On Mon, Oct 12, 2009 at 11:18 AM, Mike Driscoll <kyosohma@gmail.com> wrote:

Thanks, Werner, good to know. :smiley:
Che

···

On Mon, Oct 12, 2009 at 2:40 PM, werner <wbruhin@free.fr> wrote:

Che,

C M wrote:

On Mon, Oct 12, 2009 at 11:18 AM, Mike Driscoll <kyosohma@gmail.com> wrote:

...

Nice job hunting this down, Marco, Werner, and Mike. I was focusing
on the pubsub syntax itself and couldn't figure out why it wouldn't work,
as that part was fine, it seemed.

My remaining questions is now, in reference to Mike's point: why
does the Publisher class *not* need to put "stored" in a reference?
In other words, one can set up a listener:

Publisher().subscribe(self.__panelChangeListener, ("panel.changed"))

which is calling the class ( Publisher() ), without assigning it into a
reference--yet that listener persists. Why is this?

It is instantiated in the module itself.

Have a look around line 835 in wx.lib.pubsub (wx version 2.8.10.1).

Publisher is implemented using a pattern called Singleton
(Singleton pattern - Wikipedia).

You might also want to have a look at the new version on sourceforge
(http://pubsub.sourceforge.net/ and
http://groups.google.com/group/pypubsub). I especially like the new
documentation stuff one can do (see the attached sample file from v3
svn), i.e. one will be able to document the publisher/listener's and has
also better ways in enforcing things. Even if you use strings for your
messages you can configure it to get an exception if you try to send a
message which is not defined.

Recently played a bit with it as I wanted to learn how to do
hierarchies. If you want to look at it you should probably use the SVN
version at least when I tried it a couple of weeks ago they were a bit
out of date.

Werner