symbian-qemu-0.9.1-12/python-2.6.1/Demo/tkinter/guido/canvasevents.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #! /usr/bin/env python
       
     2 
       
     3 from Tkinter import *
       
     4 from Canvas import Oval, Group, CanvasText
       
     5 
       
     6 
       
     7 # Fix a bug in Canvas.Group as distributed in Python 1.4.  The
       
     8 # distributed bind() method is broken.  This is what should be used:
       
     9 
       
    10 class Group(Group):
       
    11     def bind(self, sequence=None, command=None):
       
    12         return self.canvas.tag_bind(self.id, sequence, command)
       
    13 
       
    14 class Object:
       
    15 
       
    16     """Base class for composite graphical objects.
       
    17 
       
    18     Objects belong to a canvas, and can be moved around on the canvas.
       
    19     They also belong to at most one ``pile'' of objects, and can be
       
    20     transferred between piles (or removed from their pile).
       
    21 
       
    22     Objects have a canonical ``x, y'' position which is moved when the
       
    23     object is moved.  Where the object is relative to this position
       
    24     depends on the object; for simple objects, it may be their center.
       
    25 
       
    26     Objects have mouse sensitivity.  They can be clicked, dragged and
       
    27     double-clicked.  The behavior may actually determined by the pile
       
    28     they are in.
       
    29 
       
    30     All instance attributes are public since the derived class may
       
    31     need them.
       
    32 
       
    33     """
       
    34 
       
    35     def __init__(self, canvas, x=0, y=0, fill='red', text='object'):
       
    36         self.canvas = canvas
       
    37         self.x = x
       
    38         self.y = y
       
    39         self.pile = None
       
    40         self.group = Group(self.canvas)
       
    41         self.createitems(fill, text)
       
    42 
       
    43     def __str__(self):
       
    44         return str(self.group)
       
    45 
       
    46     def createitems(self, fill, text):
       
    47         self.__oval = Oval(self.canvas,
       
    48                            self.x-20, self.y-10, self.x+20, self.y+10,
       
    49                            fill=fill, width=3)
       
    50         self.group.addtag_withtag(self.__oval)
       
    51         self.__text = CanvasText(self.canvas,
       
    52                            self.x, self.y, text=text)
       
    53         self.group.addtag_withtag(self.__text)
       
    54 
       
    55     def moveby(self, dx, dy):
       
    56         if dx == dy == 0:
       
    57             return
       
    58         self.group.move(dx, dy)
       
    59         self.x = self.x + dx
       
    60         self.y = self.y + dy
       
    61 
       
    62     def moveto(self, x, y):
       
    63         self.moveby(x - self.x, y - self.y)
       
    64 
       
    65     def transfer(self, pile):
       
    66         if self.pile:
       
    67             self.pile.delete(self)
       
    68             self.pile = None
       
    69         self.pile = pile
       
    70         if self.pile:
       
    71             self.pile.add(self)
       
    72 
       
    73     def tkraise(self):
       
    74         self.group.tkraise()
       
    75 
       
    76 
       
    77 class Bottom(Object):
       
    78 
       
    79     """An object to serve as the bottom of a pile."""
       
    80 
       
    81     def createitems(self, *args):
       
    82         self.__oval = Oval(self.canvas,
       
    83                            self.x-20, self.y-10, self.x+20, self.y+10,
       
    84                            fill='gray', outline='')
       
    85         self.group.addtag_withtag(self.__oval)
       
    86 
       
    87 
       
    88 class Pile:
       
    89 
       
    90     """A group of graphical objects."""
       
    91 
       
    92     def __init__(self, canvas, x, y, tag=None):
       
    93         self.canvas = canvas
       
    94         self.x = x
       
    95         self.y = y
       
    96         self.objects = []
       
    97         self.bottom = Bottom(self.canvas, self.x, self.y)
       
    98         self.group = Group(self.canvas, tag=tag)
       
    99         self.group.addtag_withtag(self.bottom.group)
       
   100         self.bindhandlers()
       
   101 
       
   102     def bindhandlers(self):
       
   103         self.group.bind('<1>', self.clickhandler)
       
   104         self.group.bind('<Double-1>', self.doubleclickhandler)
       
   105 
       
   106     def add(self, object):
       
   107         self.objects.append(object)
       
   108         self.group.addtag_withtag(object.group)
       
   109         self.position(object)
       
   110 
       
   111     def delete(self, object):
       
   112         object.group.dtag(self.group)
       
   113         self.objects.remove(object)
       
   114 
       
   115     def position(self, object):
       
   116         object.tkraise()
       
   117         i = self.objects.index(object)
       
   118         object.moveto(self.x + i*4, self.y + i*8)
       
   119 
       
   120     def clickhandler(self, event):
       
   121         pass
       
   122 
       
   123     def doubleclickhandler(self, event):
       
   124         pass
       
   125 
       
   126 
       
   127 class MovingPile(Pile):
       
   128 
       
   129     def bindhandlers(self):
       
   130         Pile.bindhandlers(self)
       
   131         self.group.bind('<B1-Motion>', self.motionhandler)
       
   132         self.group.bind('<ButtonRelease-1>', self.releasehandler)
       
   133 
       
   134     movethis = None
       
   135 
       
   136     def clickhandler(self, event):
       
   137         tags = self.canvas.gettags('current')
       
   138         for i in range(len(self.objects)):
       
   139             o = self.objects[i]
       
   140             if o.group.tag in tags:
       
   141                 break
       
   142         else:
       
   143             self.movethis = None
       
   144             return
       
   145         self.movethis = self.objects[i:]
       
   146         for o in self.movethis:
       
   147             o.tkraise()
       
   148         self.lastx = event.x
       
   149         self.lasty = event.y
       
   150 
       
   151     doubleclickhandler = clickhandler
       
   152 
       
   153     def motionhandler(self, event):
       
   154         if not self.movethis:
       
   155             return
       
   156         dx = event.x - self.lastx
       
   157         dy = event.y - self.lasty
       
   158         self.lastx = event.x
       
   159         self.lasty = event.y
       
   160         for o in self.movethis:
       
   161             o.moveby(dx, dy)
       
   162 
       
   163     def releasehandler(self, event):
       
   164         objects = self.movethis
       
   165         if not objects:
       
   166             return
       
   167         self.movethis = None
       
   168         self.finishmove(objects)
       
   169 
       
   170     def finishmove(self, objects):
       
   171         for o in objects:
       
   172             self.position(o)
       
   173 
       
   174 
       
   175 class Pile1(MovingPile):
       
   176 
       
   177     x = 50
       
   178     y = 50
       
   179     tag = 'p1'
       
   180 
       
   181     def __init__(self, demo):
       
   182         self.demo = demo
       
   183         MovingPile.__init__(self, self.demo.canvas, self.x, self.y, self.tag)
       
   184 
       
   185     def doubleclickhandler(self, event):
       
   186         try:
       
   187             o = self.objects[-1]
       
   188         except IndexError:
       
   189             return
       
   190         o.transfer(self.other())
       
   191         MovingPile.doubleclickhandler(self, event)
       
   192 
       
   193     def other(self):
       
   194         return self.demo.p2
       
   195 
       
   196     def finishmove(self, objects):
       
   197         o = objects[0]
       
   198         p = self.other()
       
   199         x, y = o.x, o.y
       
   200         if (x-p.x)**2 + (y-p.y)**2 < (x-self.x)**2 + (y-self.y)**2:
       
   201             for o in objects:
       
   202                 o.transfer(p)
       
   203         else:
       
   204             MovingPile.finishmove(self, objects)
       
   205 
       
   206 class Pile2(Pile1):
       
   207 
       
   208     x = 150
       
   209     y = 50
       
   210     tag = 'p2'
       
   211 
       
   212     def other(self):
       
   213         return self.demo.p1
       
   214 
       
   215 
       
   216 class Demo:
       
   217 
       
   218     def __init__(self, master):
       
   219         self.master = master
       
   220         self.canvas = Canvas(master,
       
   221                              width=200, height=200,
       
   222                              background='yellow',
       
   223                              relief=SUNKEN, borderwidth=2)
       
   224         self.canvas.pack(expand=1, fill=BOTH)
       
   225         self.p1 = Pile1(self)
       
   226         self.p2 = Pile2(self)
       
   227         o1 = Object(self.canvas, fill='red', text='o1')
       
   228         o2 = Object(self.canvas, fill='green', text='o2')
       
   229         o3 = Object(self.canvas, fill='light blue', text='o3')
       
   230         o1.transfer(self.p1)
       
   231         o2.transfer(self.p1)
       
   232         o3.transfer(self.p2)
       
   233 
       
   234 
       
   235 # Main function, run when invoked as a stand-alone Python program.
       
   236 
       
   237 def main():
       
   238     root = Tk()
       
   239     demo = Demo(root)
       
   240     root.protocol('WM_DELETE_WINDOW', root.quit)
       
   241     root.mainloop()
       
   242 
       
   243 if __name__ == '__main__':
       
   244     main()