1

so I was able to create a grid in python using Tkinter but I don't know how to make each cell change color when pressed on The Code:

import tkinter as tk

def create_grid(event=None):
    w = c.winfo_width() # Get current width of canvas
    h = c.winfo_height() # Get current height of canvas
    c.delete('grid_line') # Will only remove the grid_line

    # Creates all vertical lines at intevals of 100
    for i in range(0, w, 100):
        c.create_line([(i, 0), (i, h)], tag='grid_line')

    # Creates all horizontal lines at intevals of 100
    for i in range(0, h, 100):
        c.create_line([(0, i), (w, i)], tag='grid_line')

root = tk.Tk()

c = tk.Canvas(root, height=1000, width=1000, bg='white')
c.pack(fill=tk.BOTH, expand=True)

c.bind('<Configure>', create_grid)

root.mainloop()
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
Monokuma
  • 21
  • 3

2 Answers2

1

I don't exactly know what you mean by "when pressed" so I am going to assume you mean "When the mouse presses on the tile".

First step is to get the placement of the lines in an format that's easier to replicate:

lineNumber = 10 # <-- CHANGED

def create_grid(event=None):
    w = c.winfo_width() # Get current width of canvas
    h = c.winfo_height() # Get current height of canvas
    c.delete('grid_line') # Will only remove the grid_line

    for i in range(0, w, w//lineNumber): # <-- CHANGED
        c.create_line([(i, 0), (i, h)], tag='grid_line')

    for i in range(0, h, h//lineNumber): # <-- CHANGED
        c.create_line([(0, i), (w, i)], tag='grid_line')

Next step is to look for a mouse click event and calculate the targeted cube out of x and y:

def onClick(event):
    if event.num == 1: # LEFT CLICK
        cLenX = c.winfo_width()//lineNumber
        cLenY = c.winfo_height()//lineNumber

        x, y = event.x, event.y
        
        cubeX = (x-(x % cLenX)) / cLenX
        cubeY = (y-(y % cLenY)) / cLenY

        print(cubeX, cubeY)

        # canvas.create_polygon(x0, y0, x1, y1,...xn, yn, options)
        c.create_polygon(cLenX*cubeX, cLenY*cubeY, cLenX*(cubeX+1), cLenY*cubeY, cLenX*(cubeX+1), cLenY*(cubeY+1), cLenX*cubeX, cLenY*(cubeY+1), fill="red")

root.bind("<Button>", onClick)

Add that somewhere in your code and you are good to go. If you're lazy copy paste this:

import tkinter as tk

lineNumber = 10

def create_grid(event=None):
    w = c.winfo_width() # Get current width of canvas
    h = c.winfo_height() # Get current height of canvas
    c.delete('grid_line') # Will only remove the grid_line

    # Creates all vertical lines at intevals of 100
    for i in range(0, w, int(w/lineNumber)):
        c.create_line([(i, 0), (i, h)], tag='grid_line')

    # Creates all horizontal lines at intevals of 100
    for i in range(0, h, int(h/lineNumber)):
        c.create_line([(0, i), (w, i)], tag='grid_line')

root = tk.Tk()

c = tk.Canvas(root, height=500, width=500, bg='white')
c.pack(fill=tk.BOTH, expand=True)

c.bind('<Configure>', create_grid)

def onClick(event):
    if event.num == 1: # LEFT CLICK
        cLenX = int(c.winfo_width()/lineNumber)
        cLenY = int(c.winfo_height()/lineNumber)

        x, y = event.x, event.y
        
        cubeX = (x-(x % cLenX)) / cLenX
        cubeY = (y-(y % cLenY)) / cLenY

        print(cubeX, cubeY)

        # canvas.create_polygon(x0, y0, x1, y1,...xn, yn, options)
        c.create_polygon(cLenX*cubeX, cLenY*cubeY, cLenX*(cubeX+1), cLenY*cubeY, cLenX*(cubeX+1), cLenY*(cubeY+1), cLenX*cubeX, cLenY*(cubeY+1), fill="red")

root.bind("<Button>", onClick)
root.mainloop()

Actually that code is still not perfect:

  • Red tiles are drawn over black lines
  • The cubes get rectangles when you make the window to a rectangle
  • ...

I hope you figure out yourself how to solve these problems!

1

In your code please add this for loop in create_grid function

for i in range (0, w, 100):
        for j in range (0, h, 100):
          
           x=c.create_rectangle(i, j,i+100,j+100,fill='white')
           c.tag_bind(x, '<ButtonRelease-1>', onObjectClick)

then add the below function before create_grid function

def onObjectClick(event):
        x=event.widget.find_closest(event.x, event.y)[0]
        c.itemconfig(x,fill="blue")

so your full code is

import tkinter as tk
###################Add this function also###################
def onObjectClick(event):
        x=event.widget.find_closest(event.x, event.y)[0]
        c.itemconfig(x,fill="blue")
############################################################
        
def create_grid(event=None):

    global areas
    w = c.winfo_width() # Get current width of canvas
    h = c.winfo_height() # Get current height of canvas
    c.delete('grid_line') # Will only remove the grid_line

    # Creates all vertical lines at intevals of 100
    for i in range(0, w, 100):
        c.create_line([(i, 0), (i, h)], tag='grid_line')

    # Creates all horizontal lines at intevals of 100
    for i in range(0, h, 100):
        c.create_line([(0, i), (w, i)], tag='grid_line')
        
#####Add this loop#############################################   
    for i in range (0, w, 100):
        for j in range (0, h, 100):
           x=c.create_rectangle(i, j,i+100,j+100,fill='white')
           c.tag_bind(x, '<ButtonRelease-1>', onObjectClick)
           
#####Add this for loop##########################################               
  

root = tk.Tk()

c = tk.Canvas(root, height=1000, width=1000, bg='white')
c.pack(fill=tk.BOTH, expand=True)

c.bind('<Configure>', create_grid)

    
root.mainloop()
Arun K
  • 413
  • 4
  • 15