SNIP IT: tk.Canvas Drag Items Around

Phlip phlip_cpp at yahoo.com
Wed Jun 5 13:57:55 EDT 2002


phlip_cpp at yahoo.com (Phlip) wrote in message news:<63604d2.0206031518.2da29d3b at posting.google.com>...
> Hyp Ont:
> 
> Many moons ago one Tom Vrankar posted a snippet to this forum 
> regarding dragging Tkinter Canvas items around.
> 
> I have upgraded it to actually move the target items. This also 
> demonstrates canvasx and canvasy, the subject of recent mysteries.
> 
> The snippet does not make allowances for the offset between the 
> mouse point and the anchor point of the draggee; this should be 
> easy to add. But the symptom is clicking an object and starting 
> to drag makes it "snick" over to the mouse location.

This version of the snippet drags around polygons. These are trick 
because one must update all the coords, not just the first one.

import sys, os, string, time, copy
import Tkinter
tk = Tkinter

# A Python example of drag and drop functionality within a single Tk
widget.
# The trick is in the bindings and event handler functions.
# Tom Vrankar twv at ici.net

# empirical events between dropee and target, as determined from Tk
8.0
# down.
# leave.
# up, leave, enter.

class CanvasDnD (tk.Frame):
  def __init__ (self, master):
    self.master =master
    self.loc =self.dragged =0
    tk.Frame.__init__ (self, master)
    canvas =tk.Canvas (self, width =256, height =256,
      relief =tk.RIDGE, background ="white", borderwidth =1)
    self.defaultcolor =canvas.itemcget (canvas.create_text (30, 25,
      text ="Item 1", tags ="DnD"), "fill")
    
    canvas.create_text (175, 175, text ="Item 4", tags ="DnD")
    canvas.create_text (225, 225, text ="Item 5", tags ="DnD")
    x,y = 50, 200
    canvas.create_polygon(x,y, [[x+0,y+0], [x+10,y+10], [x-10,y+10]],
fill='pink', tags = 'DnD')
    x,y = 150, 40
    canvas.create_polygon(x,y, [[x+0,y+0], [x+0,y+15], [x-15,y+10]],
fill='green', tags = 'DnD')
    x,y = 120, 120
    canvas.create_polygon(x,y, [[x+0,y+0], [x+15,y+0], [x+15,y+15],
[x+0,y+15]], fill='red', tags = 'DnD')
    x,y = 120, 170
    canvas.create_polygon(x,y, [[x+0,y+0], [x+15,y+0], [x+15,y+15],
[x+0,y+15]], fill='gray', tags = 'DnD')
    canvas.pack (expand =1, fill =tk.BOTH)
    canvas.tag_bind ("DnD", "<ButtonPress-1>", self.down)
    canvas.tag_bind ("DnD", "<ButtonRelease-1>", self.chkup)
    canvas.tag_bind ("DnD", "<Enter>", self.enter)
    canvas.tag_bind ("DnD", "<Leave>", self.leave)

  def down (self, event):
#    print "Click on %s" %event.widget.itemcget (tk.CURRENT, "text")
#    print "Click on %s" % event.widget.itemconfigure (tk.CURRENT)
    print event.widget.coords(tk.CURRENT)
    self.loc =1
    self.dragged =0
    event.widget.bind ("<Motion>", self.motion)

  def motion (self, event):
    root.config (cursor ="exchange")
    cnv = event.widget
    cnv.itemconfigure (tk.CURRENT, fill ="blue")
    xy = cnv.canvasx(event.x), cnv.canvasy(event.y)
    points = event.widget.coords (tk.CURRENT)
    anchors = copy.copy(points[:2])
    print points
    
    for idx in range(len(points)):
#        print idx, xy[idx % 2], anchors[idx % 2]
        mouse = xy[idx % 2]
        zone = anchors[idx % 2]
        points[idx] = points[idx] - zone + mouse
    
    print points
    apply(event.widget.coords, [tk.CURRENT] + points)
  
  def leave (self, event):
    self.loc =0

  def enter (self, event):
    self.loc =1
    if self.dragged == event.time:
      self.up (event)

  def chkup (self, event):
    event.widget.unbind ("<Motion>")
    root.config (cursor ="")
    self.target =event.widget.find_withtag (tk.CURRENT)
    event.widget.itemconfigure (tk.CURRENT, fill =self.defaultcolor)
    if self.loc: # is button released in same widget as pressed?
      self.up (event)
    else:
      self.dragged = event.time

  def up (self, event):
    event.widget.unbind ("<Motion>")
    if (self.target ==event.widget.find_withtag (tk.CURRENT)):
      print #"Select %s" %event.widget.itemcget (tk.CURRENT, "text")
    else:
      event.widget.itemconfigure (tk.CURRENT, fill ="blue")
      self.master.update()
      time.sleep (.1)
      print "%s Drag-N-Dropped onto %s" \
        %(event.widget.itemcget (self.target, "text"),
   event.widget.itemcget (tk.CURRENT, "text"))
      event.widget.itemconfigure (tk.CURRENT, fill =self.defaultcolor)

root =tk.Tk()
root.title ("Drag-N-Drop Demo")
CanvasDnD (root).pack()
root.mainloop()

-- 
  Phlip
            http://www.greencheese.org/MakeItSo
  --  DARE to resist drug-war profiteering  --



More information about the Python-list mailing list