from tkinter import Tk, Canvas, Label, NSEW
class CanvasChecker(Canvas):
def __init__(self, parent, n_pixels_per_case=60):
self.checker = {(7, 0): 'o', (7, 2): 'o', (7, 4): 'o', (7, 6): 'o', (6, 1): 'o',
(6, 3): 'o', (6, 5): 'o', (6, 7): 'o', (5, 0): 'o', (5, 2): 'o', (5, 4): 'o',
(5, 6): 'o', (2, 1): 'x', (2, 3): 'x', (2, 5): 'x', (2, 7): 'x', (1, 0): 'x',
(1, 2): 'x', (1, 4): 'x', (1, 6): 'x', (0, 1): 'x', (0, 3): 'x', (0, 5): 'x',
(0, 7): 'x'}
self.n_pixels_per_case = n_pixels_per_case
width = 8 * n_pixels_per_case
height = 8 * n_pixels_per_case
super().__init__(parent, width=width, height=height)
self.bind('<Configure>', self.redimension)
def draw_cases(self):
for i in range(8):
for j in range(8):
beg_line = i * self.n_pixels_per_case
end_line = beg_line + self.n_pixels_per_case
beg_column = j * self.n_pixels_per_case
end_column = beg_column + self.n_pixels_per_case
if (i + j) % 2 == 0:
color = '#E88515'
color = '#DDDDFF'
self.create_rectangle(beg_column, beg_line, end_column, end_line, fill=color, tags='case')
def draw_pieces(self):
for position in self.checker:
coordinate_y = position[0] * self.n_pixels_per_case + self.n_pixels_per_case // 2
coordinate_x = position[1] * self.n_pixels_per_case + self.n_pixels_per_case // 2
piece = self.checker[position]
if piece == 'o':
icon = "\u26C0"
elif piece == 'O':
icon = "\u26C1"
elif piece == 'x':
icon = "\u26C2"
else:
icon = "\u26C3"
character_police = ('Already Seen', self.n_pixels_per_case//2)
self.create_text(coordinate_x, coordinate_y, text=icon, font=character_police, tags='piece')
def redimension(self, event):
new_size = min(event.width, event.height)
self.n_pixels_per_case = new_size // 8
self.actualise()
def actualise(self):
self.delete('case')
self.draw_cases()
self.delete('piece')
self.draw_pieces()
class Game(Tk):
def __init__(self):
super().__init__()
self.canvas_checker = CanvasChecker(self, 60)
self.canvas_checker.grid(sticky=NSEW)
self.messages = Label(self)
self.messages.grid()
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
if __name__ == '__main__':
window = Game()
window.mainloop()
I have a checker-board. I would be interested in dragging and dropping each pawn in the different cases, but I am confused how I can do it. I have thought using my_canvas.bind("<B1-Motion>", move)
, but I am not really sure how to play with that in the above code. Right now, I can only see the different white and black piece without being able to move them.
How can I drag and drop pawn on the checker-board?
All you have to do is copy some code from the highest-voted answer in the question that you linked to (in an earlier version of your question), and then adjust the bindings to work on the tag "piece" rather than "token".
First, copy the functions drag_start
, drag_stop
, and drag
from that code into your CanvasChecker
class. Change self.canvas
to self
in that copied code.
Next, add this line somewhere in the __init__
function:
self._drag_data = {"x": 0, "y": 0, "item": None}
Finally, add the following bindings, also in the __init__
:
self.tag_bind("piece", "<ButtonPress-1>", self.drag_start)
self.tag_bind("piece", "<ButtonRelease-1>", self.drag_stop)
self.tag_bind("piece", "<B1-Motion>", self.drag)
You'll need to add logic for determining whether the move is legal or not, but this answers the question about how to move the piece with the mouse.
from tkinter import Tk, Canvas, Label, NSEW
class CanvasChecker(Canvas):
def __init__(self, parent, n_pixels_per_case=60):
self.checker = {(7, 0): 'o', (7, 2): 'o', (7, 4): 'o', (7, 6): 'o', (6, 1): 'o',
(6, 3): 'o', (6, 5): 'o', (6, 7): 'o', (5, 0): 'o', (5, 2): 'o', (5, 4): 'o',
(5, 6): 'o', (2, 1): 'x', (2, 3): 'x', (2, 5): 'x', (2, 7): 'x', (1, 0): 'x',
(1, 2): 'x', (1, 4): 'x', (1, 6): 'x', (0, 1): 'x', (0, 3): 'x', (0, 5): 'x',
(0, 7): 'x'}
self.n_pixels_per_case = n_pixels_per_case
width = 8 * n_pixels_per_case
height = 8 * n_pixels_per_case
super().__init__(parent, width=width, height=height)
self.bind('<Configure>', self.redimension)
self._drag_data = {"x": 0, "y": 0, "item": None}
self.tag_bind("piece", "<ButtonPress-1>", self.drag_start)
self.tag_bind("piece", "<ButtonRelease-1>", self.drag_stop)
self.tag_bind("piece", "<B1-Motion>", self.drag)
def draw_cases(self):
for i in range(8):
for j in range(8):
beg_line = i * self.n_pixels_per_case
end_line = beg_line + self.n_pixels_per_case
beg_column = j * self.n_pixels_per_case
end_column = beg_column + self.n_pixels_per_case
if (i + j) % 2 == 0:
color = '#E88515'
color = '#DDDDFF'
self.create_rectangle(beg_column, beg_line, end_column, end_line, fill=color, tags='case')
def draw_pieces(self):
for position in self.checker:
coordinate_y = position[0] * self.n_pixels_per_case + self.n_pixels_per_case // 2
coordinate_x = position[1] * self.n_pixels_per_case + self.n_pixels_per_case // 2
piece = self.checker[position]
if piece == 'o':
icon = "\u26C0"
elif piece == 'O':
icon = "\u26C1"
elif piece == 'x':
icon = "\u26C2"
else:
icon = "\u26C3"
character_police = ('Already Seen', self.n_pixels_per_case//2)
self.create_text(coordinate_x, coordinate_y, text=icon, font=character_police, tags='piece')
def redimension(self, event):
new_size = min(event.width, event.height)
self.n_pixels_per_case = new_size // 8
self.actualise()
def actualise(self):
self.delete('case')
self.draw_cases()
self.delete('piece')
self.draw_pieces()
def drag_start(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_stop(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
class Game(Tk):
def __init__(self):
super().__init__()
self.canvas_checker = CanvasChecker(self, 60)
self.canvas_checker.grid(sticky=NSEW)
self.messages = Label(self)
self.messages.grid()
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
if __name__ == '__main__':
window = Game()
window.mainloop()