Lizi
Lizi

Reputation: 43

What is the pythonic way to display a grid?

I am learning Python and I want to display buttons in a grid. The below code produces exactly what I want, but the code for displaying the buttons by incrementing x and y does not seem very Pythonic. (I come from a procedural language background) Is there a better way? Thanks for any help.

from tkinter import *
from tkinter import ttk
root = Tk()

numberButtonsFrame = ttk.Frame(root)
numberButtonsFrame.pack()
button=[0]
for i in range(1,10):
    button.append (ttk.Button(numberButtonsFrame, text = i))

x=0
y=0
for i in range(1,10):
    button[i].grid(row=x,column=y)
    y=y+1
    if y>2:
       x=x+1
       y=0    

root.mainloop()

Upvotes: 0

Views: 104

Answers (3)

Joe Iddon
Joe Iddon

Reputation: 20414

A different method...

Using two nested loops like others have done, you can calculate the text from the row and column simply by:

(r * 3) + c + 1

Obviously, this will return an int so str() will have to be applied -leading to a more succinct solution of:

from tkinter import *
from tkinter import ttk
root = Tk()

numberButtonsFrame = ttk.Frame(root)
numberButtonsFrame.pack()

for r in range(3):
    for c in range(3):
        ttk.Button(numberButtonsFrame, text=(r * 3) + c + 1).grid(row=r, column=c)
        
root.mainloop()

Upvotes: 1

SwiftsNamesake
SwiftsNamesake

Reputation: 1578

When you're dealing with a grid, the solution is very often to use nested loops:

for row in in range(nrows):
  for col in range(ncolumns):
    buttons[row][col].grid(row=row, column=col) # You could also calculate a linear index if that's what you want

Single loop

As I noted in a comment (along with another poster), there is a way of calculating the row and column based on i (and vice versa).

row, col = divmod(i, ncolumns)

You could do this at the same time as you create each button. You could also simplify the button creation with a list comprehension.

buttons = [ttk.Button(numberButtonsFrame, text = i) for i in range(1,10)]

I assume you added the 0 at the start of your button(s) list to shift the indices: you don't have to do that. Just add 1 to i in your calculations instead.

Lastly, I would recommend using well-named variables rather than literals (eg. ncolumns). And buttonsinstead of button for the list. I'll conclude with an example (// is floor division - the div in divmod):

for i, button in enumerate(buttons):
   button.grid(row=i//ncolumns, column=i%ncolumns)

Upvotes: 2

Novel
Novel

Reputation: 13729

Use the divmod() function to calculate each row and column from the index.

buttons_per_row = 3
for i in range(9):
    button = ttk.Button(numberButtonsFrame, text = i+1)
    row, col = divmod(i, buttons_per_row)
    button.grid(row=row, column=col)

Upvotes: 1

Related Questions