user12553774
user12553774

Reputation:

Prevent resize buttons when adding text in tkinter

I made a tic tac toe game in tkinter.

Here is the code:

from tkinter import *

index = 0

def play_again():
    print("TO DO IMPLEMENT IT!")


def update(button_tekst):
    global index
    if index % 2 == 0 and button_tekst.get() == "":
        button_tekst.set("X")
        index += 1
    if index % 2 and button_tekst.get() == "":
        button_tekst.set("O")
        index += 1




def main():

    window = Tk()

    window.title("Tic tac toe")
    window.geometry("400x400")

    window.grid_columnconfigure((0,1,2), weight=1)
    window.grid_rowconfigure((1, 2, 3), weight=2)
    window.grid_rowconfigure(0, weight=1)

    again = Button(window, text="Play again", bg="lightskyblue", fg='white', font=30, command=play_again)
    again.grid(row=0, columnspan=3, sticky="ewns")

    coordinaten = [[1, 0], [1, 1], [1, 2], [2, 0],
                   [2, 1], [2, 2], [3, 0], [3, 1], [3, 2]]

    texten = [StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar(), StringVar()]

    for i in range(len(coordinaten)):
        button = Button(window, textvariable=texten[i], font=("Helvetica", "30"),  command=lambda current_index = i:update(texten[current_index]))
        button.grid(row=coordinaten[i][0], column=coordinaten[i][1], sticky="ewns")

    window.mainloop()


main()

However when i click a button the text is displayed but the button resizes automatically. How can i prevent this? Futher is it necessary to use a global index(or boolean) var and 7 Stringvar vars?

Upvotes: 0

Views: 972

Answers (1)

sciroccorics
sciroccorics

Reputation: 2427

With proportional fonts, the total width of a string depends on its content. As the geometry manager resizes each widget according to the current size of its content, you may observe the kind of annoyance you talk about. Fortunately, the solution is easy: simply specificy a constant "width" property for your Button widgets:

    button = Button(window, width=3, textvariable=texten[i], ...)

EDIT: About you other questions:

  • A global index variable is needed : YES
  • A list of 9 Stringvar is needed : NO

You may directly manipulated the 'text' property for your Button widgets. Also, by storing the 9 Buttons into a dictionary indexed by cell coordinates (i,j), your update function becomes much simpler:

from tkinter import *

def play_again():
    print("TO DO IMPLEMENT IT!")

def update(grid, i, j):
    global index
    grid[i,j]['text'] = 'XO'[index] # select either 'X' or 'O'
    index = 1 - index

def main():
    global index
    font = ("Helvetica", "30")
    index = 0

    window = Tk()
    window.title("Tic tac toe")
    window.geometry("400x400")

    window.grid_columnconfigure((0,1,2), weight=1)
    window.grid_rowconfigure((1, 2, 3), weight=2)
    window.grid_rowconfigure(0, weight=1)

    again = Button(window, text="Play again", bg="lightskyblue", fg='white',
                   font=font, command=play_again)
    again.grid(row=0, columnspan=3, sticky="ewns")

    grid = {} # store Button widgets into a dictionary indexed by cell coords
    for i in range(3):
      for j in range(3):
        grid[i,j] = Button(window, width=3, text='', font=font,
                           command=lambda i=i,j=j: update(grid, i, j))
        grid[i,j].grid(row=i+1, column=j, sticky="ewns")

    window.mainloop()

main()

Upvotes: 1

Related Questions