pythonpython-3.xtkintertkinter-canvas

Tkinter canvas rectangle appears with incorrect size depending on row/column – how to fix?


I am writing a Python tkinter rectangle function:

def Rectangle(row,col,color="#FFFFFF",outline="gray"):
    """
    Fills a block with a color.
    Args:
        row - The row 
        col - The column
        *color - The rectangle color
        *outline - The color of the outline
    """
    global blockwidth, blockheight, canvas
    x, y, i = blockCoords(row,col)
    canvas.create_rectangle(x//2,y//2,x*2,y*2,fill=color,outline=outline)

This function should make a rectangle at those (row, col) coordinates exactly one block (rectangle in the drawn grid, explained later) big.

def blockCoords(row, col):
    """
    Gets the row and col value of a digit.
    Args:
        rows - The block's row
        cols - The block's col
    Returns:
        The x and y coordinates and it's respective index
    """
    global blockwidth, blockheight, canwidth, canheight
    row -= 1
    col -= 1
    x = col * blockwidth + blockwidth // 2
    y = row * blockheight + blockheight // 2
    i = row+col
    return x, y, i

Then the rectangle function is called in the main function:

blockwidth = 20
blockheight = 40
win = tk.Tk()
states = []
win.title("Terminos App")
with open("set.json","r") as f:
    settings = json.load(f)

# create a canvas
canwidth = 1200
canheight = 800
canvas = tk.Canvas(win,width=canwidth,height=canheight,bg="#232627")
canvas.pack(fill=tk.BOTH,expand=tk.YES)

def main():
    """
    The main function that handles the window
    Args:
        event - A detected keypress
    """
    global win, canvas, canwidth, canheight, blockwidth, blockheight
    cols = canwidth//blockwidth
    rows = canheight//blockheight
    for row in range(canwidth):
        for col in range(canheight):
            states.append("")
            x1 = col * blockwidth
            y1 = row * blockheight
            x2 = x1 + blockwidth
            y2 = y1 + blockheight
            canvas.create_rectangle(x1, y1, x2, y2, outline="gray") # Used for debugging purposes
    Rectangle(10,15)

The code should create the rectangle I explained, but it creates one with a different size depending on the row and col coordinates. What is the problem and what is the solution? Thanks!


Solution

  • You're currently treating the center point (x, y) as if it were the top-left and bottom-right corners. Instead of x//2 and x*2, calculate the corners based on width and height like this:

    
    canvas.create_rectangle(x - blockwidth // 2, y - blockheight // 2,
                            x + blockwidth // 2, y + blockheight // 2,
                            fill=color, outline=outline)
    

    That way, the rectangle will be exactly blockwidth × blockheight in size, centred at the calculated coordinates.