如何通过单击 canvas 小部件来协调数组值和 tkinter canvas 的变化?
How can I coordinate the change in array value and tkinter canvas by clicking on canvas widget?
我开发了一个十六进制游戏接口,它获取一个二维数组(白色单元格的值为 1,黑色单元格的值为 2,
0 为空单元格)和屏幕上第一个六边形的坐标作为输入,并根据第一个
绘制十六进制的 table
点.
我想触发鼠标左键单击的动作,将单元格的值更改为 1 或 2(这意味着播放
点击单元格中的白色或黑色宝石)。当我单击单元格并打印数组时,游戏中单击单元格的值
棋盘变了,但点击的六边形颜色没有变
除非点击触发器中的图形发生变化,否则这是正确的代码。
from tkinter import *
class gui:
"""
This class is built to let the user have a better interaction with
game.
inputs =>
canvas = Canvas(root)
board = board is the array of gamestate class which shows the game board.
start_points = This entry indicates an array of points which is the top
left coordinate of item of the graphical interface.
"""
def __init__(self, root, start_points, board):
self.canvas = Canvas(root, width=900, height=768)
self.board = board
self.start = [start_points[0], start_points[1], start_points[2],
start_points[3], start_points[4], start_points[5]]
self.temp = []
for i in self.start:
self.temp.append(i)
self.initial_offset = 20 # Offset for each row and first item
self.hex_x = 40 # Offset for each hexagon in each row
self.hex_y = 40 # Offset from top of screen
self.hex_board = []
self.array_to_hex(self.board)
self.bind()
self.canvas.pack(anchor='nw')
def hexagon(self, points, color):
"""
Creates a hexagon by getting a list of points and their assigned colors
according to the game board
"""
if color is 0:
hx = self.canvas.create_polygon(points[0], points[1], points[2],
points[3], points[4], points[5],
fill='#fe8b03', outline='black', width=2)
elif color is 1:
hx = self.canvas.create_polygon(points[0], points[1], points[2],
points[3], points[4], points[5],
fill='white', outline='black', width=2)
else:
hx = self.canvas.create_polygon(points[0], points[1], points[2],
points[3], points[4], points[5],
fill='#3e3f3a', outline='black', width=2)
return hx
def genrow(self, points, colors):
"""
By getting a list of points as the starting point of each row and a list of
colors as the dedicated color for each item in row, it generates a row of
hexagons by calling hexagon functions multiple times.
"""
row = []
temp_array = []
for i in range(len(colors)):
for point in points:
temp_points_x = point[0] + self.hex_x * i
temp_points_y = point[1]
temp_array.append([temp_points_x, temp_points_y])
if colors[i] is 0:
hx = self.hexagon(temp_array, 0)
elif colors[i] is 1:
hx = self.hexagon(temp_array, 1)
else:
hx = self.hexagon(temp_array, 2)
row.append(hx)
temp_array = []
return row
def array_to_hex(self, array):
"""
Simply gets the gameboard and generates the hexagons by their dedicated colors.
"""
for i in range(len(array)):
for point in self.temp:
point[0] += self.hex_x
point[1] += self.hex_y
for point in self.temp:
point[0] -= self.initial_offset
row = self.genrow(self.temp, self.board[i])
self.temp.clear()
for k in self.start:
self.temp.append(k)
self.hex_board.append(row)
def bind(self):
"""
Binding triggers for the actions defined in the class.
"""
self.canvas.bind('<Motion>', self.mouse_motion)
self.canvas.bind('<1>', self.mouse_click)
def mouse_motion(self, event):
"""
Simply implements a hovering action for each item
"""
if self.canvas.find_withtag(CURRENT):
current_color = self.canvas.itemcget(CURRENT, 'fill')
self.canvas.itemconfig(CURRENT, fill="cyan")
self.canvas.update_idletasks()
self.canvas.after(150)
self.canvas.itemconfig(CURRENT, fill=current_color)
def mouse_click(self, event):
"""
This function changes the color of item (depending on the player turns)
to assigned color
"""
x, y = event.x, event.y
idd = self.canvas.find_overlapping(x, y, x, y)
idd = list(idd)
if len(idd) is not 0:
p = idd[0]
index = [[ix, iy] for ix,
row in enumerate(self.hex_board) for iy,
i in enumerate(row) if i == p][0]
self.board[index[0]][index[1]] = 1
for i in self.board:
print(i)
print('\n')
row_item_offset = 40
x_offset = 20
y_offset = 40
points1 = [[25, 10], [45, 25], [45, 50], [25, 65], [5, 50], [5, 25]]
test_array = [[1, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 0, 0],
[1, 1, 1, 2, 1, 2],
[0, 0, 0, 2, 0, 2],
[0, 1, 0, 0, 1, 2],
[0, 0, 0, 2, 0, 0]]
root = Tk()
hexagons = gui(root, points1, test_array)
root.mainloop()
我有点想刷新整个项目或使用 forget 方法删除整个小部件并重新打包,但我
不知道如何实现。
我想我需要修改 mouse_click_trigger 方法。
谁能对示例代码提出任何建议?
谢谢。
我真的希望这就是您要找的:
from tkinter import *
root = Tk()
root.geometry("600x600-400+50")
root.title("Game")
class App:
def __init__(self, master):
self.master = master
self.rbvar = IntVar()
self.stonerb = Radiobutton(self.master, text="Stone",
variable=self.rbvar, value=1, command=self.figurefunc)
self.stonerb.pack()
self.blackrb = Radiobutton(self.master, text="Black",
variable=self.rbvar, value=2, command=self.figurefunc)
self.blackrb.pack()
self.board = Canvas(self.master, bg='#b35900', width=500, height=500)
self.board.pack()
self.figure = self.board.create_polygon(0,0, 0,0, 0,0, 0,0, 0,0, 0,0)
self.stoneCoords = 60,200, 100,200, 120,230, 100,260, 60,260, 40,230
self.blackCoords = 440,200, 400,200, 380,230, 400,260, 440,260, 460,230
def figurefunc(self):
if self.rbvar.get() == 1:
self.board.coords(self.figure, self.stoneCoords)
self.board.itemconfig(self.figure, fill='#f2f2f2')
else:
self.board.coords(self.figure, self.blackCoords)
self.board.itemconfig(self.figure, fill='black')
myapp = App(root)
呸!
我开发了一个十六进制游戏接口,它获取一个二维数组(白色单元格的值为 1,黑色单元格的值为 2,
0 为空单元格)和屏幕上第一个六边形的坐标作为输入,并根据第一个
绘制十六进制的 table点.
我想触发鼠标左键单击的动作,将单元格的值更改为 1 或 2(这意味着播放
点击单元格中的白色或黑色宝石)。当我单击单元格并打印数组时,游戏中单击单元格的值
棋盘变了,但点击的六边形颜色没有变
除非点击触发器中的图形发生变化,否则这是正确的代码。
from tkinter import *
class gui:
"""
This class is built to let the user have a better interaction with
game.
inputs =>
canvas = Canvas(root)
board = board is the array of gamestate class which shows the game board.
start_points = This entry indicates an array of points which is the top
left coordinate of item of the graphical interface.
"""
def __init__(self, root, start_points, board):
self.canvas = Canvas(root, width=900, height=768)
self.board = board
self.start = [start_points[0], start_points[1], start_points[2],
start_points[3], start_points[4], start_points[5]]
self.temp = []
for i in self.start:
self.temp.append(i)
self.initial_offset = 20 # Offset for each row and first item
self.hex_x = 40 # Offset for each hexagon in each row
self.hex_y = 40 # Offset from top of screen
self.hex_board = []
self.array_to_hex(self.board)
self.bind()
self.canvas.pack(anchor='nw')
def hexagon(self, points, color):
"""
Creates a hexagon by getting a list of points and their assigned colors
according to the game board
"""
if color is 0:
hx = self.canvas.create_polygon(points[0], points[1], points[2],
points[3], points[4], points[5],
fill='#fe8b03', outline='black', width=2)
elif color is 1:
hx = self.canvas.create_polygon(points[0], points[1], points[2],
points[3], points[4], points[5],
fill='white', outline='black', width=2)
else:
hx = self.canvas.create_polygon(points[0], points[1], points[2],
points[3], points[4], points[5],
fill='#3e3f3a', outline='black', width=2)
return hx
def genrow(self, points, colors):
"""
By getting a list of points as the starting point of each row and a list of
colors as the dedicated color for each item in row, it generates a row of
hexagons by calling hexagon functions multiple times.
"""
row = []
temp_array = []
for i in range(len(colors)):
for point in points:
temp_points_x = point[0] + self.hex_x * i
temp_points_y = point[1]
temp_array.append([temp_points_x, temp_points_y])
if colors[i] is 0:
hx = self.hexagon(temp_array, 0)
elif colors[i] is 1:
hx = self.hexagon(temp_array, 1)
else:
hx = self.hexagon(temp_array, 2)
row.append(hx)
temp_array = []
return row
def array_to_hex(self, array):
"""
Simply gets the gameboard and generates the hexagons by their dedicated colors.
"""
for i in range(len(array)):
for point in self.temp:
point[0] += self.hex_x
point[1] += self.hex_y
for point in self.temp:
point[0] -= self.initial_offset
row = self.genrow(self.temp, self.board[i])
self.temp.clear()
for k in self.start:
self.temp.append(k)
self.hex_board.append(row)
def bind(self):
"""
Binding triggers for the actions defined in the class.
"""
self.canvas.bind('<Motion>', self.mouse_motion)
self.canvas.bind('<1>', self.mouse_click)
def mouse_motion(self, event):
"""
Simply implements a hovering action for each item
"""
if self.canvas.find_withtag(CURRENT):
current_color = self.canvas.itemcget(CURRENT, 'fill')
self.canvas.itemconfig(CURRENT, fill="cyan")
self.canvas.update_idletasks()
self.canvas.after(150)
self.canvas.itemconfig(CURRENT, fill=current_color)
def mouse_click(self, event):
"""
This function changes the color of item (depending on the player turns)
to assigned color
"""
x, y = event.x, event.y
idd = self.canvas.find_overlapping(x, y, x, y)
idd = list(idd)
if len(idd) is not 0:
p = idd[0]
index = [[ix, iy] for ix,
row in enumerate(self.hex_board) for iy,
i in enumerate(row) if i == p][0]
self.board[index[0]][index[1]] = 1
for i in self.board:
print(i)
print('\n')
row_item_offset = 40
x_offset = 20
y_offset = 40
points1 = [[25, 10], [45, 25], [45, 50], [25, 65], [5, 50], [5, 25]]
test_array = [[1, 0, 0, 0, 0, 0],
[0, 0, 2, 0, 0, 0],
[1, 1, 1, 2, 1, 2],
[0, 0, 0, 2, 0, 2],
[0, 1, 0, 0, 1, 2],
[0, 0, 0, 2, 0, 0]]
root = Tk()
hexagons = gui(root, points1, test_array)
root.mainloop()
我有点想刷新整个项目或使用 forget 方法删除整个小部件并重新打包,但我
不知道如何实现。 我想我需要修改 mouse_click_trigger 方法。 谁能对示例代码提出任何建议? 谢谢。
我真的希望这就是您要找的:
from tkinter import *
root = Tk()
root.geometry("600x600-400+50")
root.title("Game")
class App:
def __init__(self, master):
self.master = master
self.rbvar = IntVar()
self.stonerb = Radiobutton(self.master, text="Stone",
variable=self.rbvar, value=1, command=self.figurefunc)
self.stonerb.pack()
self.blackrb = Radiobutton(self.master, text="Black",
variable=self.rbvar, value=2, command=self.figurefunc)
self.blackrb.pack()
self.board = Canvas(self.master, bg='#b35900', width=500, height=500)
self.board.pack()
self.figure = self.board.create_polygon(0,0, 0,0, 0,0, 0,0, 0,0, 0,0)
self.stoneCoords = 60,200, 100,200, 120,230, 100,260, 60,260, 40,230
self.blackCoords = 440,200, 400,200, 380,230, 400,260, 440,260, 460,230
def figurefunc(self):
if self.rbvar.get() == 1:
self.board.coords(self.figure, self.stoneCoords)
self.board.itemconfig(self.figure, fill='#f2f2f2')
else:
self.board.coords(self.figure, self.blackCoords)
self.board.itemconfig(self.figure, fill='black')
myapp = App(root)
呸!