Reputation: 165
def drag_and_drop(self):
"""
Method allowing to drag and drop a pawn
"""
if self.game.onOff.get() == 1:
self._drag_data = {"x": 0, "y": 0, "item": None}
self.tag_bind("piece", "<ButtonPress-1>", self.drag_beg)
self.tag_bind("piece", "<ButtonRelease-1>", self.drag_end)
self.tag_bind("piece", "<B1-Motion>", self.drag)
else:
do_Something()
def drag_beg(self, event):
"""Begining drag of an object"""
# record the item and its location
self._drag_data["item"] = self.find_closest(event.x, event.y)[0]
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
def drag_end(self, event):
"""End drag of an object"""
# reset the drag information
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
def drag(self, event):
"""Handle dragging of an object"""
# compute how much the mouse has moved
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]
# move the object the appropriate amount
self.move(self._drag_data["item"], delta_x, delta_y)
# record the new position
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
The code above allows me to drag and drop a pawn in a checkerboard. The drag_and_drop
function is associated with a checkbutton (i.e. with tkinter). When I check the box in my interface, the drag and drop is activated. When I unchecked the box, I would like to bring back the old setup, i.e. I click once on a case source and I click a second time target case to move the pawn to the new case. I think I have to implement the method do_Something()
to deactivate the drag-and-drop feature? How can I do that?
When I check the box, the drag-and-drop is very well activated, but when I unchecked the box, the function drag-and-drop is still activated. I have not found a way to deactivated it.
UPDATE
Can I unbind it this way?
self.tag_bind("piece", "<ButtonPress-1>")
self.tag_bind("piece", "<ButtonRelease-1>")
self.tag_bind("piece", "<B1-Motion>")
Upvotes: 1
Views: 208
Reputation: 16169
There are several ways of switching on and off the drag and drop feature.
As asked by the OP, it is possible to unbind the tag bindings:
The use of tag_unbind
is pretty straightforward: .tag_unbind(<tag>, <sequence>)
will unbind all bindings to the given sequence for items with given tag. In this case:
def drag_and_drop(self):
"""
Method allowing to drag and drop a pawn
"""
if self.game.onOff.get() == 1:
self._drag_data = {"x": 0, "y": 0, "item": None}
self.tag_bind("piece", "<ButtonPress-1>", self.drag_beg)
self.tag_bind("piece", "<ButtonRelease-1>", self.drag_end)
self.tag_bind("piece", "<B1-Motion>", self.drag)
else:
self.tag_unbind("piece", "<ButtonPress-1>")
self.tag_unbind("piece", "<ButtonRelease-1>")
self.tag_unbind("piece", "<B1-Motion>")
Below is a full example:
import tkinter as tk
class Board(tk.Canvas):
def __init__(self, master, drag_enabled, **kw):
tk.Canvas.__init__(self, master, **kw)
self.drag_enabled = drag_enabled
self._drag_data = {"x": 0, "y": 0, "item": None}
self.create_oval(10, 10, 50, 50, fill='white', tags='piece')
def drag_and_drop(self):
"""
Method allowing to drag and drop a pawn
"""
if self.drag_enabled.get():
self._drag_data = {"x": 0, "y": 0, "item": None}
self.tag_bind("piece", "<ButtonPress-1>", self.drag_beg)
self.tag_bind("piece", "<ButtonRelease-1>", self.drag_end)
self.tag_bind("piece", "<B1-Motion>", self.drag)
else:
self.tag_unbind("piece", "<ButtonPress-1>")
self.tag_unbind("piece", "<ButtonRelease-1>")
self.tag_unbind("piece", "<B1-Motion>")
def drag_beg(self, event):
"""Begining drag of an object"""
# record the item and its location
self._drag_data["item"] = self.find_closest(event.x, event.y)[0]
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
def drag_end(self, event):
"""End drag of an object"""
# reset the drag information
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
def drag(self, event):
"""Handle dragging of an object"""
# compute how much the mouse has moved
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]
# move the object the appropriate amount
self.move(self._drag_data["item"], delta_x, delta_y)
# record the new position
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
root = tk.Tk()
drag_enabled = tk.BooleanVar(root)
board = Board(root, drag_enabled)
tk.Checkbutton(root, text='Enable drag', variable=drag_enabled,
command=board.drag_and_drop).pack(side='bottom')
board.pack()
root.mainloop()
As suggested in the comments, it is possible to check whether drag and drop is activated inside the functions called by the bindings and return without doing anything if it is disabled. Something like:
def <drag function>(self, event):
if self.drag_enabled.get():
# drag and drop actions
In this case, the drag_and_drop()
function is not needed and can be put into the initialization of the board:
import tkinter as tk
class Board(tk.Canvas):
def __init__(self, master, drag_enabled, **kw):
tk.Canvas.__init__(self, master, **kw)
self.drag_enabled = drag_enabled
self._drag_data = {"x": 0, "y": 0, "item": None}
self.create_oval(10, 10, 50, 50, fill='white', tags='piece')
self._drag_data = {"x": 0, "y": 0, "item": None}
self.tag_bind("piece", "<ButtonPress-1>", self.drag_beg)
self.tag_bind("piece", "<ButtonRelease-1>", self.drag_end)
self.tag_bind("piece", "<B1-Motion>", self.drag)
def drag_beg(self, event):
"""Begining drag of an object"""
# record the item and its location
if self.drag_enabled.get():
self._drag_data["item"] = self.find_closest(event.x, event.y)[0]
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
def drag_end(self, event):
"""End drag of an object"""
# reset the drag information
self._drag_data["item"] = None
self._drag_data["x"] = 0
self._drag_data["y"] = 0
def drag(self, event):
"""Handle dragging of an object"""
# compute how much the mouse has moved
if self.drag_enabled.get():
delta_x = event.x - self._drag_data["x"]
delta_y = event.y - self._drag_data["y"]
# move the object the appropriate amount
self.move(self._drag_data["item"], delta_x, delta_y)
# record the new position
self._drag_data["x"] = event.x
self._drag_data["y"] = event.y
root = tk.Tk()
drag_enabled = tk.BooleanVar(root)
b = Board(root, drag_enabled)
tk.Checkbutton(root, text='Enable drag', variable=drag_enabled).pack(side='bottom')
b.pack(fill='both', expand=True)
root.mainloop()
Upvotes: 1