nwhaught
nwhaught

Reputation: 1592

Python/Tkinter: Update button text after delay

I'm writing a simple little slapjack game to get acquainted with Python and Tkinter. I've got a button for the player to take their turn, but I'm stuck on how to get the computer to take its turn.

This will have the computer take its turn, but does not update the text on lbl_btn until deal() returns, meaning that I never see the card that the human played:

lbl_btn = Button(root, textvariable=varCard, command=lambda: slap()).pack()
deal_btn = Button(root, text="deal", command=lambda: deal()).pack()

def deal():
    varTurn.get() % 2 == 0
    pile.append(human.deck[0])
    human.deck.remove(human.deck[0])
    update_label()
    root.after(2000)
    pile.append(compy.deck[0])
    compy.deck.remove(compy.deck[0])
    update_label()


def update_label():
    varTurn.set(varTurn.get()+1)
    print(pile[len(pile)-1].name)
    varCard.set(pile[len(pile)-1].name)

This version of deal() shows the correct label after each button click, but is non-optimal because the computer's turn requires a separate click:

def deal():
if varTurn.get() % 2 == 0:
    pile.append(human.deck[0])
    human.deck.remove(human.deck[0])
else:
    pile.append(compy.deck[0])
    compy.deck.remove(compy.deck[0])
varTurn.set(varTurn.get()+1)
print(pile[len(pile)-1].name)
varCard.set(pile[len(pile)-1].name)

I know that the label button isn't updating until my lambda completes, but in that case, how can I create a separate call to deal after a delay that will result in updating the value of lbl_btn?

Upvotes: 0

Views: 1466

Answers (1)

Jason S
Jason S

Reputation: 119

If I understand what you're asking, you might be looking for Tk.update(). If you call root.update() right before root.after(2000), this will do a force refresh and cause Tkinter to update the UI.

As an example (I modified your code):

from Tkinter import *

deck1 = ['A', 'B', 'C']
deck2 = ['D', 'E', 'F']
pile = []

def deal():
    varTurn.get() % 2 == 0
    pile.append(deck1[0])
    deck1.remove(deck1[0])
    update_label()
    root.update()
    root.after(2000)
    pile.append(deck2[0])
    deck2.remove(deck2[0])
    update_label()


def update_label():
    varTurn.set(varTurn.get()+1)
    print(pile[len(pile)-1])
    varCard.set(pile[len(pile)-1])

root = Tk()
varCard = StringVar()
varTurn = IntVar()
lbl_btn = Button(root, textvariable=varCard, command=lambda: slap()).pack()
deal_btn = Button(root, text="deal", command=lambda: deal()).pack()
root.mainloop()

This causes the top button text to be refreshed immediately after the new card is drawn. Note that this ultimately might not be the best way to implement your game because even though the button updates to display the new card, the GUI will be unresponsive while waiting for the deal() function to complete.

Upvotes: 3

Related Questions