Tkinter, python 3.8.1, win10Pro, How can I change a label image?

自闭症网瘾萝莉.ら 提交于 2021-01-29 14:55:41

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!