0

So I'm creating the game of life in python, and would like to create a grid on top of a canvas using the tkinter class of python. Thanks in advance.

To make the grid I'm using the create_line() function of the canvas class and looping through using the range() function so that my lines are drawn to the width and the height of the canvas, using two separate for loops one for width and one for the height. The loops I have gotten are taken from the following piece of code on stackoverflow: How to create a grid on tkinter in python? I thought I understood what is happening but what I thought should happen has not

from tkinter import *
from random import *

window = Tk()
window.title('Game Of Life')
canvas = Canvas(window, background='white', width=800, height=600)


def create_grid(canvas):
    width = canvas.winfo_width() # gets width of the canvas
    height = canvas.winfo_height() # gets height of the canvas

    for line in range(0, width, 1): # range(start, stop, step)
        canvas.create_line([(line, 0), (line, height)], fill='black', tags='grid_line_w')

    for line in range(0, height, 1):
        canvas.create_line([(0, line), (width, line)], fill='black', tags='grid_line_h')


create_grid(canvas)
canvas.grid(row=0, column=0)
window.mainloop()

My expected results are to have a white canvas with vertical and horizontal lines stretching the width and height of the canvas. But my actual results are just a white canvas with no lines on top.

user2152012
  • 161
  • 1
  • 4
  • 17
  • You can use `winfo_reqwidth()` and `winfo_reqheight()` instead of `winfo_width()` and `winfo_height()`. – acw1668 Mar 27 '19 at 01:46

1 Answers1

3

I don't trust winfo_width and winfo_height to give accurate values in this context. According to https://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.winfo_height-method, the functions simply return 1 if you haven't packed/gridded/placed the widget yet, and even if you have, it might still return 1 if the window's event loop hasn't updated lately. You already know that you want the width to be 800 and the height to be 600, so you may as well define them as such directly.

Another problem is that your range calls have a step argument of 1. This means that the lines will be one pixel apart, which will effectively paint the entire canvas black. I recommend a larger step.

from tkinter import *
from random import *

window = Tk()
window.title('Game Of Life')

def create_grid(window):
    width = 800
    height = 600
    canvas = Canvas(window, background='white', width=width, height=height)


    for line in range(0, width, 10): # range(start, stop, step)
        canvas.create_line([(line, 0), (line, height)], fill='black', tags='grid_line_w')

    for line in range(0, height, 10):
        canvas.create_line([(0, line), (width, line)], fill='black', tags='grid_line_h')

    canvas.grid(row=0, column=0)

create_grid(window)
window.mainloop()

Result:

enter image description here

Kevin
  • 74,910
  • 12
  • 133
  • 166
  • 2
    `winfo_width` and `winfo_height` are trustworthy, but only to the extent that they are designed to be. Until the window is actually made visible, it's size is going to be 1x1 (and this is the documented behavior). I realize that's more-or-less what you said, but the way you said it gives the impression that the calls randomly fail. They don't fail, they simply return the actual size of the widget. – Bryan Oakley Mar 26 '19 at 19:15
  • Kevin & Bryan Oakley thanks I appreciate the help a bunch :) – user2152012 Mar 26 '19 at 19:22
  • @user2152012 please ping people with @ so they get a notification –  Mar 27 '19 at 03:33
  • @Programmer will do next time – user2152012 Mar 27 '19 at 17:19