0

I am currently using the following code to create a grid the size of the window within python using the tkinter module

import tkinter as tk

class Frame():

    def __init__(self, *args, **kwargs):
        # Setup Canvas
        self.c = tk.Canvas(root, height=500, width=500, bg='white')
        self.c.pack(fill=tk.BOTH, expand=True)
        self.c.bind('<Configure>', self.createGrid)
        self.pixel_width = 20
        self.pixel_height = 20

        # Setup binds
        self.c.bind("<ButtonPress-1>", self.leftClick)

    def leftClick(self, event):
        items = self.c.find_closest(event.x, event.y)
        if items:
            rect_id = items[0]
            self.c.itemconfigure(rect_id, fill="red")

    def createGrid(self, event=None):
        for x in range(0, self.c.winfo_width()):
            for y in range(0, self.c.winfo_height()):
                x1 = (x * self.pixel_width)
                x2 = (x1 + self.pixel_width)
                y1 = (y * self.pixel_height)
                y2 = (y1 + self.pixel_height)
                self.c.create_rectangle(x1,y1,x2,y2)
        self.c.update()

root = tk.Tk()
gui = Frame(root)
root.mainloop()

If I set the canvas height and width to something like 50 this loads quite quickly, although when the size is increased to 500 x 500 like is set here it takes about 5 seconds to create the grid. I have tried creating the grid with lines but the problem with that is I need squares as I am then planning to change the colour of a square that is selected. Is there any way I can make this more efficient?

hcphoon
  • 538
  • 5
  • 24
  • Drawing it with lines is definitely faster (as in [this answer](https://stackoverflow.com/a/34011751/7315159)), but if you need to colour a specific square, couldn't you just draw the squares when they're clicked, as in [this answer](https://stackoverflow.com/a/50780915/7315159)? – Niayesh Isky Mar 17 '19 at 06:39
  • @NiayeshIsky I dont think that would work as I need the square to snap to the grid line, that would just create a square wherever I click – hcphoon Mar 17 '19 at 07:14
  • Well, you can just do some quick math each time to get the bounds of the square in which the user clicked. You just need to round to the nearest multiple of whatever your square width is, which should give you one of the corners, and then you can use that to calculate the coordinates of the other corners. – Niayesh Isky Mar 17 '19 at 07:21
  • I added a count to your `createGrid` function and you created 254016 squares for 500x500 which definitely will slow up. You might need to change the way you create the sqaures. – Henry Yik Mar 17 '19 at 08:27

1 Answers1

0

I think you created way more rectangles than you need. The below two lines:

for x in range(0, self.c.winfo_width()):
        for y in range(0, self.c.winfo_height()):

Will create 504x504 rectangles = 254016. It will work fine if you reduce it to just fill your current screen:

def createGrid(self, event=None):
    for x in range(0, int(self.c.winfo_width()/20+1)):
        for y in range(0, int(self.c.winfo_height()/20+1)):
            x1 = (x * self.pixel_width)
            x2 = (x1 + self.pixel_width)
            y1 = (y * self.pixel_height)
            y2 = (y1 + self.pixel_height)
            self.c.create_rectangle(x1,y1,x2,y2)
    self.c.update()
Henry Yik
  • 22,275
  • 4
  • 18
  • 40