我正在做一个项目,用矩形创建自然数的逆时针螺旋。下面显示了一个示例:
螺旋自然数:
我希望能够使用 Tkinter grid() 或画布创建这些螺旋矩形,直到达到某个值,而不是带有数字的颜色。在图像中,停止值为 13,有 13 个矩形。
我有网格框架:
import tkinter as tk
class GridCanvas(tk.Canvas):
def __init__(self, master=None, **kwargs):
tk.Canvas.__init__(self, master, **kwargs)
self.bind("<B1-Motion>", self.draw_rectangle)
self.grid_size = 20 # Adjust the grid size as needed
self.draw_grid()
def draw_grid(self):
for i in range(0, self.winfo_reqwidth(), self.grid_size):
self.create_line(i, 0, i, self.winfo_reqheight(), fill="gray", dash=(2, 2))
for i in range(0, self.winfo_reqheight(), self.grid_size):
self.create_line(0, i, self.winfo_reqwidth(), i, fill="gray", dash=(2, 2))
def draw_rectangle(self, event):
x, y = event.x, event.y
x1 = (x // self.grid_size) * self.grid_size
y1 = (y // self.grid_size) * self.grid_size
x2 = x1 + self.grid_size
y2 = y1 + self.grid_size
self.create_rectangle(x1, y1, x2, y2, outline="black", fill="blue", stipple="gray50")
if __name__ == "__main__":
root = tk.Tk()
root.title("Grid Canvas")
canvas = GridCanvas(root, width=400, height=400, bg="white")
canvas.pack(expand=tk.YES, fill=tk.BOTH)
root.mainloop()
但我无法找到创建矩形的方法。如果有人有任何疑问,我很乐意澄清。任何指导将不胜感激。预先感谢。
您可能需要发电机循环方向
up
,left
,down
,right
def cycle_direction():
# (dx, dy)
values = (
( 0,-1), # up
(-1, 0), # left
( 0, 1), # down
( 1, 0), # right
)
while True:
for x in values:
yield x
(当然你可以使用
itertools.cycle()
)
和生成器计算下次改变方向之前的长度。
好像两次改变方向后长度就增加了
(+1, +1, +2, +2, +3, +3, ....)
def length():
size = 1
while True:
yield size
yield size
size += 1
现在需要嵌套循环。首先获取方向和大小,其次绘制矩形。
我将
draw_rectangle()
转换为普通函数,得到 x, y, color
所以我在代码中使用它。
def run_example(self):
# start position
x = 200
y = 200
# draw first rectangle
self.draw_rectangle(x, y)
root.update() # force tkinter to redraw window
time.sleep(0.5) # slow down to see how it change
# generators
gen_direction = cycle_direction()
gen_length = length()
gen_color = cycle_color()
for _ in range(10):
dx, dy = next(gen_direction)
l = next(gen_length)
#c = next(gen_color)
for _ in range(l):
x += (dx * self.grid_size)
y += (dy * self.grid_size)
print( (dx, dy) , x, y)
self.draw_rectangle(x, y) #, color=c)
root.update() # force tkinter to redraw window
time.sleep(0.5) # slow down to see how it change
def on_mouse_motion(self, event):
self.draw_rectangle(event.x, event.y)
def draw_rectangle(self, x, y, color="blue"):
x1 = (x // self.grid_size) * self.grid_size
y1 = (y // self.grid_size) * self.grid_size
x2 = x1 + self.grid_size
y2 = y1 + self.grid_size
self.create_rectangle(x1, y1, x2, y2, outline="black", fill=color, stipple="gray50")
仍然需要计算细胞数才能在正确的时刻改变颜色。
完整的工作代码(后图):
我在显示画布后使用
self.after
开始示例。
我使用
time.sleep()
只是为了显示它如何变化。
import tkinter as tk
import time
def length():
size = 1
while True:
yield size
yield size
size += 1
def cycle_direction():
# (dx, dy)
values = (
( 0,-1), # up
(-1, 0), # left
( 0, 1), # down
( 1, 0), # right
)
while True:
for x in values:
yield x
def cycle_color():
values = ("blue", 'red', 'green', 'yellow')
while True:
for x in values:
yield x
class GridCanvas(tk.Canvas):
def __init__(self, master=None, **kwargs):
tk.Canvas.__init__(self, master, **kwargs)
self.bind("<B1-Motion>", self.on_mouse_motion)
self.grid_size = 20 # Adjust the grid size as needed
self.draw_grid()
# run after showing canvas
self.after(1000, self.run_example)
def run_example(self):
# start position
x = 200
y = 200
# draw first rectangle
self.draw_rectangle(x, y)
root.update() # force tkinter to redraw window
time.sleep(0.5) # slow down to see how it change
# generators
gen_direction = cycle_direction()
gen_length = length()
gen_color = cycle_color()
for _ in range(10):
dx, dy = next(gen_direction)
l = next(gen_length)
#c = next(gen_color)
for _ in range(l):
x += (dx * self.grid_size)
y += (dy * self.grid_size)
print( (dx, dy) , x, y)
self.draw_rectangle(x, y) #, color=c)
root.update() # force tkinter to redraw window
time.sleep(0.5) # slow down to see how it change
def draw_grid(self):
for i in range(0, self.winfo_reqwidth(), self.grid_size):
self.create_line(i, 0, i, self.winfo_reqheight(), fill="gray", dash=(2, 2))
for i in range(0, self.winfo_reqheight(), self.grid_size):
self.create_line(0, i, self.winfo_reqwidth(), i, fill="gray", dash=(2, 2))
def on_mouse_motion(self, event):
self.draw_rectangle(event.x, event.y)
def draw_rectangle(self, x, y, color="blue"):
x1 = (x // self.grid_size) * self.grid_size
y1 = (y // self.grid_size) * self.grid_size
x2 = x1 + self.grid_size
y2 = y1 + self.grid_size
self.create_rectangle(x1, y1, x2, y2, outline="black", fill=color, stipple="gray50")
if __name__ == "__main__":
root = tk.Tk()
root.title("Grid Canvas")