问题
This is my VERY first post so forgive my newness. I'm trying to make a GUI of a dice rolling game (2 x six-sided). Logic of the random rolls is working fine to console. Also in console I see that die number is mapping to correct image file, but I'm having trouble changing tkinter label images to the new corresponding images on every roll beyond the initial startup roll.
On startup, it displays both die images correctly, but when I click "roll" button, both images from first roll just disappear and new roll images are not displayed. It just blanks the space previously occupied by first roll images.
Looking closely, I can see the correct die images "flash" on screen in their correct positions only to immediately disappear each time I press "roll".
I'm unable to attach the six images I'm using for the possible die rolls (lack of creds), but point is to demonstrate ability to change from any image to any other so feel free to try with any 6 gifs.
I saw similar questions on this site but when I tried code suggested, or combos of code suggested, I had same problem I am having now.
I'm using python 3.8.1 on win10pro. Any help would be appreciated! Here's my code:
from tkinter import *
import random
window = Tk()
window.title( 'Roller' )
window.resizable( 0, 0 )
def get_roll():
min=1
max=6
die1 = random.randint(min,max)
die2 = random.randint(min,max)
if die1 == die2:
print(die1,'+',die2,'=',die1+die2, '*** You rolled doubles ***')
else:
print(die1,'+',die2,'=',die1+die2)
return die1,die2
def get_image(index):
images = []
images.append('die_01_42158_sm.gif')
images.append('die_02_42159_sm.gif')
images.append('die_03_42160_sm.gif')
images.append('die_04_42161_sm.gif')
images.append('die_05_42162_sm.gif')
images.append('die_06_42164_sm.gif')
return images[index-1]
def do_roll():
global window
die1, die2 = get_roll()
imgfile1 = get_image(die1)
imgfile2 = get_image(die2)
print(imgfile1)
img1 = PhotoImage( file = imgfile1 )
#img1 = img1.subsample(20)
imgLbl1.configure( image = img1 )
#imgLbl1 = Label( window, image = img1 )
#imgLbl1.grid(row = 0, column = 0)
window.update_idletasks()
print(imgfile2)
img2 = PhotoImage( file = imgfile2 )
#img2 = img2.subsample(20)
imgLbl2.configure( image = img2 )
#imgLbl2 = Label( window, image = img2 )
#imgLbl2.grid(row = 0, column = 1)
window.update_idletasks()
die1, die2 = get_roll()
imgfile1 = get_image(die1)
imgfile2 = get_image(die2)
img1 = PhotoImage( file = imgfile1 )
#img1 = img1.subsample(20)
imgLbl1 = Label( window, image = img1 )
imgLbl1.grid( row = 0, column = 0 )
img2 = PhotoImage( file = imgfile2 )
#img2 = img2.subsample(20)
imgLbl2 = Label( window, image = img2 )
imgLbl2.grid( row = 0, column = 1 )
rollBtn = Button( window )
rollBtn.grid( row = 0, column = 2 )
rollBtn.configure( text = 'Roll' )
rollBtn.configure( command = do_roll )
quitBtn = Button( window )
quitBtn.grid( row = 0, column = 3 )
quitBtn.configure( text = 'Quit' )
quitBtn.configure( command = window.destroy )
#do_roll()
window.mainloop()
回答1:
Since you used local variables to hold the images, they will be garbage collected after the function.
You have to keep the references of the images:
def do_roll():
die1, die2 = get_roll()
imgfile1 = get_image(die1)
imgfile2 = get_image(die2)
print(imgfile1)
imgLbl1.image = PhotoImage(file=imgfile1)
imgLbl1.configure(image=imgLbl1.image)
print(imgfile2)
imgLbl2.image = PhotoImage(file=imgfile2)
imgLbl2.configure(image=imgLbl2.image)
Or declare img1
and img2
as global:
def do_roll():
global img1, img2
die1, die2 = get_roll()
imgfile1 = get_image(die1)
imgfile2 = get_image(die2)
print(imgfile1)
img1 = PhotoImage(file=imgfile1)
imgLbl1.configure(image=img1)
print(imgfile2)
img2 = PhotoImage(file=imgfile2)
imgLbl2.configure(image=img2)
回答2:
Using acw1668's solution above I was able to build upon that to complete my goal of simulating rolls of a pair of dice. Initially, the dice go through 10 random tosses then stop at the tenth as the 'roll'. Each subsequent press of the roll button causes same. My desired programmatic goal was to demonstrate that a label image could be changed multiple times. Here's the code (but you'll have to provide your own images for the 6 sides of the die - sorry, can't download with low creds):
from tkinter import *
import random
def get_roll():
min=1
max=6
die1 = random.randint(min,max)
die2 = random.randint(min,max)
if die1 == die2:
print(die1,'+',die2,'=',die1+die2, '*** You rolled doubles ***')
else:
print(die1,'+',die2,'=',die1+die2)
return die1,die2
def get_image(index):
images = []
images.append('die_01_42158_sm.gif')
images.append('die_02_42159_sm.gif')
images.append('die_03_42160_sm.gif')
images.append('die_04_42161_sm.gif')
images.append('die_05_42162_sm.gif')
images.append('die_06_42164_sm.gif')
return images[index-1]
counter = 0
def counter_label():
global counter
print('counter_label() counter =', counter)
def count():
global counter, imgLbl1, imgLbl2
print('count() counter =', counter)
print(counter)
counter += 1
if counter > 10:
return
die1, die2 = get_roll()
imgfile1 = get_image(die1)
imgLbl1.image = PhotoImage( file = imgfile1 )
imgLbl1.configure( image = imgLbl1.image )
imgfile2 = get_image(die2)
imgLbl2.image = PhotoImage( file = imgfile2 )
imgLbl2.configure( image = imgLbl2.image )
imgLbl1.after(10, count)
if counter >= 10:
counter = 0
count()
root = Tk()
root.title("Counting Seconds")
imgLbl1 = Label(root)
imgLbl1.pack(side =LEFT)
imgLbl2 = Label(root)
imgLbl2.pack(side =LEFT)
counter_label()
buttonr = Button(root, text='Roll', width=25, command=counter_label)
buttonr.pack()
buttonq = Button(root, text='Stop', width=25, command=root.destroy)
buttonq.pack()
root.mainloop()
来源:https://stackoverflow.com/questions/60312754/tkinter-python-3-8-1-win10pro-how-can-i-change-a-label-image