创建网格图形 Tkinter

问题描述 投票:0回答:1

我正在做一个项目,用矩形创建自然数的逆时针螺旋。下面显示了一个示例:

螺旋自然数: spiral natural numbers

我希望能够使用 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()

但我无法找到创建矩形的方法。如果有人有任何疑问,我很乐意澄清。任何指导将不胜感激。预先感谢。

python tkinter graphics
1个回答
0
投票

您可能需要发电机循环方向

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")
© www.soinside.com 2019 - 2024. All rights reserved.