-1

We are creating a Boggle game for school, and we want to make the interface as as nice as possible. We created an icon for each letter and we want each button to have it's icon. For some reason is doesnt work, and I can't figure out why - it only designate an image for the last button (as shown in the picture). This is my code:

import tkinter as tk
import random
import os


PATH_DICT = {"A": "\icons\A.png", "B": "\icons\B.png", "C": "\icons\C.png",
             "D": "\icons\D.png", "E": "\icons\E.png", "F": "\icons\F.png",
             "G": "\icons\G.png", "H": "\icons\H.png", "I": "\icons\I.png",
             "J": "\icons\J.png", "K": "\icons\K.png", "L": "\icons\L.png",
             "M": "\icons\M.png", "N": "\icons\MN.png", "O": "\icons\O.png",
             "P": "\icons\P.png", "Qu": "\icons\Qu.png", "R": "\icons\R.png",
             "S": "\icons\S.png", "T": "\icons\T.png", "U": "\icons\TU.png",
             "V": "\icons\J.png", "W": "\icons\W.png", "X": "\icons\X.png",
             "Y": "\icons\Y.png", "Z": "\icons\Z.png"}

root = tk.Tk()


def randomize_board():
    letters = [
        ['A', 'E', 'A', 'N', 'E', 'G'],
        ['A', 'H', 'S', 'P', 'C', 'O'],
        ['A', 'S', 'P', 'F', 'F', 'K'],
        ['O', 'B', 'J', 'O', 'A', 'B'],
        ['I', 'O', 'T', 'M', 'U', 'C'],
        ['R', 'Y', 'V', 'D', 'E', 'L'],
        ['L', 'R', 'E', 'I', 'X', 'D'],
        ['E', 'I', 'U', 'N', 'E', 'S'],
        ['W', 'N', 'G', 'E', 'E', 'H'],
        ['L', 'N', 'H', 'N', 'R', 'Z'],
        ['T', 'S', 'T', 'I', 'Y', 'D'],
        ['O', 'W', 'T', 'O', 'A', 'T'],
        ['E', 'R', 'T', 'T', 'Y', 'L'],
        ['T', 'O', 'E', 'S', 'S', 'I'],
        ['T', 'E', 'R', 'W', 'H', 'V'],
        ['N', 'U', 'I', 'H', 'M', 'Qu']
    ]

    board = []
    for i in range(4):
        row = []
        for j in range(4):
            letter = random.choice(letters[i * 4 + j])
            row.append(letter)
        board.append(row)
    return board


ls = randomize_board()
CURR_DIR = os.path.dirname(os.path.abspath(__file__))
image_lst = []
for x in range(4):
    for y in range(4):
        i = 0
        photo1 = tk.PhotoImage(file=CURR_DIR + PATH_DICT[ls[x][y]])
        btn = tk.Button(image=photo1, bg="SkyBlue", activebackground="white",
                        padx=20, pady=20,  command=lambda x=x, y=y: getclick(x, y))
        btn.grid(row=y, column=x)
        i += 1



root.mainloop()

What am I doing wrong? Thank you!

Enmar
  • 1
  • Can you share those images? I want to debug your program on my PC – Alderven Jan 17 '20 at 08:26
  • ***"What am I doing wrong?"***: You overwrite the reference `photo1` again and again. Follow this approach: [way-of-avoiding-unwanted-garbage-collection](https://stackoverflow.com/questions/58788728/in-tkinter-is-this-a-good-way-of-avoiding-unwanted-garbage-collection/58791160#58791160) – stovfl Jan 17 '20 at 08:36
  • Just add `btn.image = photo1` after `btn.grid(...)`. – acw1668 Jan 17 '20 at 09:28

1 Answers1

0

Here is a little test that works for me :

import tkinter as tk
import random
from PIL import ImageTk, Image

PATH_DICT = {
    "A": "icons/A.png",
    "B": "icons/B.png",
    "C": "icons/C.png"
}

root = tk.Tk()

def randomize_board():
    letters = [
        ['A', 'A', 'A', 'B'],
        ['A', 'A', 'A', 'B'],
        ['A', 'A', 'A', 'B'],
        ['A', 'A', 'C', 'A']
    ]

    board = []
    for i in range(4):
        row = []
        for j in range(4):
            letter = random.choice(letters[i * 4 + j])
            row.append(letter)
        board.append(row)
    return board


# ls = randomize_board()
ls = [
        ['A', 'A', 'A', 'B'],
        ['A', 'A', 'A', 'B'],
        ['A', 'A', 'A', 'B'],
        ['A', 'A', 'C', 'A']
    ]

def create_img(frame, path_to_img):
    width = 100
    height = 140

    img = Image.open(path_to_img)
    img = img.resize((width,height), Image.ANTIALIAS)
    photoImg =  ImageTk.PhotoImage(img)
    btn= tk.Button(frame, image=photoImg, width=width)
    return btn

buttons_list = []

for x in range(4):
    row_btns = []
    for y in range(4):
        row_btns.append(create_img(root, PATH_DICT[ls[x][y]]))
        row_btns[y].grid(row=y, column=x)
    buttons_list.append(row_btns)

root.mainloop()

I cannot test the following code since I don't have all the necessary, but it should work for you :

import tkinter as tk
import random
from PIL import ImageTk, Image

PATH_DICT = {"A": "\icons\A.png", "B": "\icons\B.png", "C": "\icons\C.png",
            "D": "\icons\D.png", "E": "\icons\E.png", "F": "\icons\F.png",
            "G": "\icons\G.png", "H": "\icons\H.png", "I": "\icons\I.png",
            "J": "\icons\J.png", "K": "\icons\K.png", "L": "\icons\L.png",
            "M": "\icons\M.png", "N": "\icons\MN.png", "O": "\icons\O.png",
            "P": "\icons\P.png", "Qu": "\icons\Qu.png", "R": "\icons\R.png",
            "S": "\icons\S.png", "T": "\icons\T.png", "U": "\icons\TU.png",
            "V": "\icons\J.png", "W": "\icons\W.png", "X": "\icons\X.png",
            "Y": "\icons\Y.png", "Z": "\icons\Z.png"}

root = tk.Tk()

def randomize_board():
    letters = [
        ['A', 'E', 'A', 'N', 'E', 'G'],
        ['A', 'H', 'S', 'P', 'C', 'O'],
        ['A', 'S', 'P', 'F', 'F', 'K'],
        ['O', 'B', 'J', 'O', 'A', 'B'],
        ['I', 'O', 'T', 'M', 'U', 'C'],
        ['R', 'Y', 'V', 'D', 'E', 'L'],
        ['L', 'R', 'E', 'I', 'X', 'D'],
        ['E', 'I', 'U', 'N', 'E', 'S'],
        ['W', 'N', 'G', 'E', 'E', 'H'],
        ['L', 'N', 'H', 'N', 'R', 'Z'],
        ['T', 'S', 'T', 'I', 'Y', 'D'],
        ['O', 'W', 'T', 'O', 'A', 'T'],
        ['E', 'R', 'T', 'T', 'Y', 'L'],
        ['T', 'O', 'E', 'S', 'S', 'I'],
        ['T', 'E', 'R', 'W', 'H', 'V'],
        ['N', 'U', 'I', 'H', 'M', 'Qu']
    ]

    board = []
    for i in range(4):
        row = []
        for j in range(4):
            letter = random.choice(letters[i * 4 + j])
            row.append(letter)
        board.append(row)
    return board

ls = randomize_board()

def create_img(frame, path_to_img):
    width = 100
    height = 140

    img = Image.open(path_to_img)
    img = img.resize((width,height), Image.ANTIALIAS)
    photoImg =  ImageTk.PhotoImage(img)

    btn = tk.Button(frame, image=photoImg, bg="SkyBlue", activebackground="white",
                        padx=20, pady=20,  command=lambda x=x, y=y: getclick(x, y))
    return btn

buttons_list = []

for x in range(4):
    row_btns = []
    for y in range(4):
        row_btns.append(create_img(root, PATH_DICT[ls[x][y]]))
        row_btns[y].grid(row=y, column=x)
    buttons_list.append(row_btns)

root.mainloop()
Phoenixo
  • 2,071
  • 1
  • 6
  • 13