Reputation: 43
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
Reputation: 20414
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
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
As I noted in a comment (along with another poster), there is a way of calculating the row
and col
umn 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 buttons
instead 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
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