问题
I'm trying to make a memory card matching game in python and I have a folder called 'icons' that has the 21 images that I want to use.
I created the buttons in a 6x7 grid using for loops. I put the buttons in a list called buttons
which I will later use to keep track of which buttons are still empty and are available for putting images.
Using a for loop, I loop over the images in the folder. For each image, I choose a random button from the list which will contain the image. I then remove that button from the buttons
list so that it is not chosen again. I do that twice for each image. Here is my code:
from tkinter import *
from pathlib import Path
import random
root = Tk()
root.geometry('600x700')
root.title('Memory Game')
icon_dir = Path('C:\\Users\\Talal\\PycharmProjects\\HelloWorld\\icons')
frm_grid = Frame(root)
frm_grid.rowconfigure([0, 1, 2, 3, 4, 5, 6], weight=1, minsize=2)
frm_grid.columnconfigure([0, 1, 2, 3, 4, 5], weight=1, minsize=2)
frm_grid.pack(fill=BOTH, expand=YES)
buttons = []
for row in range(0, 7):
for column in range(0, 6):
btn = Button(frm_grid)
btn.grid(row=row, column=column, sticky='news')
buttons.append(btn)
for file in icon_dir.iterdir():
icon = PhotoImage(file=str(file))
btn = random.choice(buttons)
btn.config(image=icon)
buttons.remove(btn)
btn = random.choice(buttons)
btn.config(image=icon)
buttons.remove(btn)
root.mainloop()
However, when the code is executed, only the last image in the folder is displayed. It does display twice on two random buttons every time, so at least it displays correctly.
I wanted to show you a picture, but I am new to Stack Overflow so I unfortunately am not allowed do that yet, so I will describe it. There is a 6x7 grid of buttons in the window. every time I run the program, the last image in the folder is displayed on only 2 buttons, and the rest are empty.
I tried changing the order of the images in the folder to make sure it wasn't related to that specific image, but when I moved them, the new one displayed.
Thank you in advance!
回答1:
Since you used same variable icon
to hold the reference of PhotoImage
instances, so only the final image has variable reference to it. The other images will then be garbage collected.
Add btn.image = icon
after each btn.config(image=icon)
to keep a reference of the image:
for file in icon_dir.iterdir():
icon = PhotoImage(file=str(file))
btn = random.choice(buttons)
btn.config(image=icon)
btn.image = icon # keep a reference to the image
buttons.remove(btn)
btn = random.choice(buttons)
btn.config(image=icon)
btn.image = icon # keep a reference to the image
buttons.remove(btn)
回答2:
This line: for file in icon_dir.iterdir():
, you are systematically iterating over each image in the directory one after the other, You need to select the images at random from the directory not sequentially.
It goes like this:
/icon_dir
|_img1
|_img2
|_img3
First it assigns img1 to two buttons and removes them, then it assigns img2 to two buttons and removes them then it assigns img3(aka the last image in the folder) to the displayed buttons which you see.
You can use this random.choice(os.listdir(icon_dir))
to get a random image
来源:https://stackoverflow.com/questions/62696252/trying-to-put-images-from-a-folder-onto-tkinter-buttons-only-the-last-image-is