Hello,
When creating an application you often have to call upon methods or attributes that are located in other objects. Most often in a wx.Python environment you do this by calling it's parent. (ex. parent.My_ListBox.InsertItem("test", 0))
This can result in very complex code (ex. self.parent.GetParent().parent.GetParent().Widget.Method())
Are there better way's of traversing the parent/child tree ?
Regards,
Jonas Geiregat
jonas@geiregat.org
Hi Jonas,
Hello,
When creating an application you often have to call upon methods or
attributes that are located in other objects. Most often in a
wx.Python environment you do this by calling it's parent. (ex.
parent.My_ListBox.InsertItem("test", 0))
This can result in very complex code (ex.
self.parent.GetParent().parent.GetParent().Widget.Method())
Are there better way's of traversing the parent/child tree ?
Regards,
Jonas Geiregat
jo...@geiregat.org
Actually, you shouldn't do it that way. If you have multiple instances
(or windows) that need to communicate, you should check out pubsub. Of
course, there are a ton of better methods to use too, like
GetTopLevelParent or GetGrandParent.
In a lot of cases, you pass a parent to the class and you can grab
that. For example, if I have the following in a Panel class:
wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
I can grab the parent and make it a method like so:
self.parent = parent
Now I can call the parent's methods and such (i.e.
self.parent.Widget.GetValue() ), but this is a hack. In this case, I
should really use pubsub as it is much cleaner. Here's a couple of
links:
http://wiki.wxpython.org/PubSub
http://wiki.wxpython.org/Controlling%20GUI%20with%20pubsub
I hope that helps some...
···
On Oct 6, 2:33 pm, Jonas Geiregat <jo...@geiregat.org> wrote:
-------------------
Mike Driscoll
Blog: http://blog.pythonlibrary.org
wx.Panel.init(self, parent=parent, id=wx.ID_ANY)
I can grab the parent and make it a method like so:
self.parent = parent
Now I can call the parent’s methods and such (i.e.
self.parent.Widget.GetValue() ), but this is a hack. In this case, I
should really use pubsub as it is much cleaner. Here’s a couple of
links:
My code is written in the exact same way as above. Only it needs to traverse large tree.
I’ve never heard of pubsub and well check it out!
Thanks!
Mike Driscoll wrote:
When creating an application you often have to call upon methods or attributes that are located in other objects. Most often in a wx.Python environment you do this by calling it's parent.
I don't
I think you should think of wxPython's parent-child hierarchy as an implementation detail, and not use it that way -- it's very fragile if you refactor the interface a lot, and violates the "Law of Demeter". IN other words, a given class shouldn't have to know what its parent's parent's parent is!
You have two other choice:
Total decoupling: this means passing messages with pubsub or the like, as Mike suggested.
Keeping references -- in the simplest case, you keep a reference directly to any objects you need to manipulate in each class that need to manipulate them. A more complex, but more flexible, way it to have a class that keeps track of all the objects that need to be manipulated.
You also may want to encapsulate your GUI more -- rather than manipulating the widgets directly.
parent.My_ListBox.InsertItem("test", 0))
so this should be more like:
self.List_Thingy.AddItem(something)
where List_Thingy is a class you've written that represents whatever that list is -- if may well use a ListBox to represent it, but that should be independent of its API.
Take a look in the wxPython wiki under MVC and MVP for more ideas.
-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
Mike Driscoll wrote:
>> When creating an application you often have to call upon methods or
>> attributes that are located in other objects. Most often in a
>> wx.Python environment you do this by calling it's parent.
I don't
I guess I was thinking of the examples that I've seen on the wiki and
in the demo...or something.
I think you should think of wxPython's parent-child hierarchy as an
implementation detail, and not use it that way -- it's very fragile if
you refactor the interface a lot, and violates the "Law of Demeter". IN
other words, a given class shouldn't have to know what its parent's
parent's parent is!
This is a good point! I'll have to tuck it away to bring out for the
new newb...
You have two other choice:
Total decoupling: this means passing messages with pubsub or the like,
as Mike suggested.
Keeping references -- in the simplest case, you keep a reference
directly to any objects you need to manipulate in each class that need
to manipulate them. A more complex, but more flexible, way it to have a
class that keeps track of all the objects that need to be manipulated.
You also may want to encapsulate your GUI more -- rather than
manipulating the widgets directly.
>> parent.My_ListBox.InsertItem("test", 0))
so this should be more like:
self.List_Thingy.AddItem(something)
where List_Thingy is a class you've written that represents whatever
that list is -- if may well use a ListBox to represent it, but that
should be independent of its API.
Take a look in the wxPython wiki under MVC and MVP for more ideas.
-Chris
--
Christopher Barker, Ph.D.
Oceanographer
As usual, you have some fun and interesting ideas that I've not tried.
I may have to mess with some of them in the future.
···
On Oct 6, 3:55 pm, Christopher Barker <Chris.Bar...@noaa.gov> wrote:
-------------------
Mike Driscoll
Blog: http://blog.pythonlibrary.org
I do agree with Christopher that most of the time accessing parents in
the ownership hierarchy violates the “Law of mosaic” , but in few
cases some “kaleidoscopic” behaviour might be desirable:
-
One obvious example when access to the parents hierarchy is useful is
an automatic gui code generation.
-
Another example is when child non-top components may change their
size or shape. In this case if such child did not update layout of its
parent, then each parent in the hierarchy would have to implement its
own event handler to deal with its children reshaping/resizing (see
wx.lib.expando.ExpandoTextCtrl for instance).
-
There are also some more complex examples related the database access
gui, where child access to its parent might be useful.
perhaps, there are more examples can be found.
Following function can be used to find a parent (ancestor) which
conforms certain criterion set by predicate:
`def GetWxAncestor(child, predicate=lambda parent: True):
parent = child.GetParent()
while parent is not None:
if predicate(parent):
return parent
else:
return GetWxAncestor(instance, predicate)
return None`
For example, to find a wx parent, which is instance of DataPathProvider
class, you might call GetWxAncestor(childInstance, predicate=lambda parent: isinstance(parent, DataPathProvider))
.
Victor
···
Chris.Barker@noaa.gov
wxpython-users@googlegroups.com
Mike Driscoll wrote:
When creating an application you often have to call upon methods or attributes that are located in other objects. Most often in a wx.Python environment you do this by calling it's parent.
I don't ;-)
I think you should think of wxPython's parent-child hierarchy as an implementation detail, and not use it that way -- it's very fragile if you refactor the interface a lot, and violates the "Law of Demeter". IN other words, a given class shouldn't have to know what its parent's parent's parent is!
You have two other choice:
Total decoupling: this means passing messages with pubsub or the like, as Mike suggested.
Keeping references -- in the simplest case, you keep a reference directly to any objects you need to manipulate in each class that need to manipulate them. A more complex, but more flexible, way it to have a class that keeps track of all the objects that need to be manipulated.
You also may want to encapsulate your GUI more -- rather than manipulating the widgets directly.
parent.My_ListBox.InsertItem("test", 0))
so this should be more like:
self.List_Thingy.AddItem(something)
where List_Thingy is a class you've written that represents whatever that list is -- if may well use a ListBox to represent it, but that should be independent of its API.
Take a look in the wxPython wiki under MVC and MVP for more ideas.
-Chris
Correction:
There was a mistake in GetWxAncestor()
function in my
previous post. Correct function is this:
`def GetWxAncestor(child, predicate=lambda parent: True):
parent = ``child``.GetParent()
while parent is not None:
if predicate(parent):
return parent
else:
return GetWxAncestor(parent, predicate)
return None`
The following is an interactive session, which demonstrates/validates
its operation:
`>>> import wx
class TheirPanel(wx.Panel):
… pass
…
class HerPanel(wx.Panel):
… pass
…
class MyPanel(wx.Panel):
… pass
…
f = wx.Frame(None)
tp = TheirPanel(f)
hp = HerPanel(tp)
mp = MyPanel(hp)
p = wx.Panel(mp)
def GetWxAncestor(child
,
predicate=lambda parent: True):
… parent = child
.GetParent()
… while parent is not None:
… if predicate(parent):
… return parent
… else:
… return GetWxAncestor(parent, predicate)
… return None
…
a = GetWxAncestor(p)
a == mp
True
a = GetWxAncestor(p, lambda parent: isinstance(parent,
TheirPanel))
a == tp
True
a = GetWxAncestor(p, lambda parent: isinstance(parent,
HerPanel))
a == hp
True
`
Victor
···
v.rybynok@gmail.com
wxpython-users@googlegroups.com
I do agree with Christopher that most of the time accessing parents in
the ownership hierarchy violates the “Law of mosaic” , but in few
cases some “kaleidoscopic” behaviour might be desirable:
-
One obvious example when access to the parents hierarchy is useful is
an automatic gui code generation.
-
Another example is when child non-top components may change their
size or shape. In this case if such child did not update layout of its
parent, then each parent in the hierarchy would have to implement its
own event handler to deal with its children reshaping/resizing (see
wx.lib.expando.ExpandoTextCtrl for instance).
-
There are also some more complex examples related the database access
gui, where child access to its parent might be useful.
perhaps, there are more examples can be found.
Following function can be used to find a parent (ancestor) which
conforms certain criterion set by predicate:
`def GetWxAncestor(child, predicate=lambda parent: True):
parent = child.GetParent()
while parent is not None:
if predicate(parent):
return parent
else:
return GetWxAncestor(instance, predicate)
return None`
For example, to find a wx parent, which is instance of DataPathProvider
class, you might call GetWxAncestor(childInstance, predicate=lambda parent: isinstance(parent, DataPathProvider))
.
Victor
-------- Original Message --------
Subject: [wxPython-users] Re: calling widgets parents parents
From: Christopher Barker To: Date: 06 October 2009 21:55:36
Chris.Barker@noaa.gov
wxpython-users@googlegroups.com
Mike Driscoll wrote:
When creating an application you often have to call upon methods or attributes that are located in other objects. Most often in a wx.Python environment you do this by calling it's parent.
I don't ;-)
I think you should think of wxPython's parent-child hierarchy as an implementation detail, and not use it that way -- it's very fragile if you refactor the interface a lot, and violates the "Law of Demeter". IN other words, a given class shouldn't have to know what its parent's parent's parent is!
You have two other choice:
Total decoupling: this means passing messages with pubsub or the like, as Mike suggested.
Keeping references -- in the simplest case, you keep a reference directly to any objects you need to manipulate in each class that need to manipulate them. A more complex, but more flexible, way it to have a class that keeps track of all the objects that need to be manipulated.
You also may want to encapsulate your GUI more -- rather than manipulating the widgets directly.
parent.My_ListBox.InsertItem("test", 0))
so this should be more like:
self.List_Thingy.AddItem(something)
where List_Thingy is a class you've written that represents whatever that list is -- if may well use a ListBox to represent it, but that should be independent of its API.
Take a look in the wxPython wiki under MVC and MVP for more ideas.
-Chris