On Sun, 30 Jan 2005, Glen wrote:

> As a Python/Tkinter newbie, I thought I was getting on ok...
> then I hit this problem.
>
> I have a canvas (c1)
> A group of objects are drawn on c1 and given a tag
>       c1.addtag_all('group_A')

> Another group of objects are drawn, I wish to tag these 'group_B'.


Hi Glen,

Ok, so you're looking for something like a hypothetical "find_withouttag"
to define 'group_B' then.  I don't think such a function exists directly,
but we can make it up.


> At the moment I 'get by' with...
>
>     a=c1.find_withtag('group_A')
>     b=c1.find_all()
>     c=b[len(a):]
>     for i in range(len(c)):
>         c1.addtag_above('group_B',len(a)+i)


There's one problem here: the system doesn't guarantee that all the
'group_A' elememts will end up at the beginning of 'b', so there's a very
strong possibility of tagging the wrong elements here.


I think that getting this right will take some more work.  Here's a
definition of a function called find_withouttag():

###
def find_withouttag(canvas, tag):
    """Returns all the objects that aren't tagged with 'tag'."""
    all_objects = canvas.find_all()
    tagged_objects = canvas.find_withtag(tag)
    return subtract_instances(all_objects, tagged_objects)


def subtract_instances(l1, l2):
    """Returns a list of all the object instances in l1 that aren't in
       l2."""
    identity_dict = {}
    for x in l1:
        identity_dict[id(x)] = x
    for x in l2:
        if id(x) in identity_dict:
            del identity_dict[id(x)]
    return identity_dict.values()
###

[Side note to other: the work that subtract_instances() does is similar to
what IdentityHashMap does in Java: does anyone know if there's already an
equivalent dictionary implementation of IdentityHashMap in Python?]


We can see how subtract_instances() works on a simple example:

###
>>> class MyClass:
...     def __init__(self, name):
...         self.name = name
...     def __repr__(self):
...         return str(self.name)
...
>>> frodo, elrond, arwen, aragorn, sam, gimli = (
...    map(MyClass, "Frodo Elrond Arwen Aragorn Sam Gimli".split()))
>>> hobbits = frodo, sam
>>> everyone = frodo, elrond, arwen, aragorn, sam, gimli
>>>
>>> subtract_instances(everyone, hobbits)
[Arwen, Aragorn, Gimli, Elrond]
###


This subtract_instances() function should do the trick with instances of
the canvas items.  There's probably a simpler way to do this --- and there
are things we can do to make it more efficient --- but I have to go to
sleep at the moment.  *grin*


Best of wishes to you!

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to