I'm trying to simulate a GUI as part of a larger card game, using python's tKinter. This GUI asks the user to enter a desired number of cards, press the deal button, and then it updates the buttons on the screen to display a random deck of that number of cards (as buttons). My issue is that each time the deal button is pressed, the new card buttons are simply added to the old ones. I have tried to incorporate a Destroy method under the myButtons class, and then calling the method each time the 'Deal' button is clicked, but this does not seem to work either.
import random
from tkinter import *
root = Tk()
def deal(n):
deck = Deck()
deck.shuffle()
cards = []
for number in range(n):
card = deck.deal()
cards.append(card)
return cards
class myButtons(Frame):
def __init__(self, parent, Cards):
Frame.__init__(self, parent)
self.Cards = Cards
for Card in Cards:
self.SingleButton = Button(self)
self.SingleButton['text'] = Card
self.SingleButton.pack()
class Card:
def __init__(self, f, s):
self.myFaceValue = f
self.mySuit = s
def __str__(self):
return self.myFaceValue ' of ' self.mySuit
def faceValue(self):
return self.myFaceValue
def suit(self):
return self.mySuit
class Deck:
faceValues = ['ace', '2', '3', '4', '5', '6', '7', '8',
'9', '10', 'jack', 'queen', 'king']
suits = ['clubs', 'diamonds', 'hearts', 'spades']
def __init__(self):
self.theCards = [Card(faceValue, suit)
for faceValue in Deck.faceValues
for suit in Deck.suits]
self.shuffle()
def shuffle(self):
random.shuffle(self.theCards)
def deal(self):
return self.theCards.pop()
def cardsLeft(self):
return len(self.theCards)
class enhancedEntry(Frame):
def __init__(self, parent, prompt, actionText, action):
Frame.__init__(self, parent)
self.inputBoxLabel = Label(self)
self.inputBoxLabel['text'] = prompt
self.inputBoxLabel.pack(side=LEFT, fill=X)
self.inputBox = Entry(self)
self.inputBox.pack(side=LEFT, fill=X)
self.button = Button(self)
self.button['text'] = actionText
self.button['command'] = action
self.button.pack(side=LEFT, fill=X)
def get(self):
return self.inputBox.get()
def setActionText(self, actionText):
self.button['text'] = actionText
def setPrompt(self, prompt):
self.inputBoxLabel['text'] = prompt
def setAction(self, cmd):
self.button['command'] = cmd
def dealCards():
#reset myButtonsFrame
myButtons.destroy
num = userInput.get()
if num.isdigit():
number = int(num)
if 0<number<=52:
myCards = deal(number)
displayedButtons = myButtons(root, myCards)
displayedButtons.pack()
else:
input('This is not a number')
return
userInput = enhancedEntry(root, 'Enter # of cards:', 'Deal', dealCards)
userInput.pack(fill=X)
mainloop()
How can I use the destroy function to destroy the myButtons class Frame each time the 'Deal' button is clicked such that is can reset/refresh the GUI to display only the desired number of cards?
CodePudding user response:
I believe you can use the function pack_forget()
.
widget.pack_forget()
This should remove the widget from the window
CodePudding user response:
It is better to create instance of myButtons
without any button inside first, then remove existing buttons and create the required number of buttons after user inputs the number.
...
class myButtons(Frame):
# create number of cards given
def deal(self, Cards):
self.Cards = Cards
for Card in Cards:
Button(self, text=Card, width=20).pack()
...
def dealCards():
# delete existing buttons
for w in displayedButtons.winfo_children():
w.destroy()
num = userInput.get()
if num.isdigit():
number = int(num)
if 0<number<=52:
myCards = deal(number)
displayedButtons.deal(myCards)
else:
input('This is not a number')
return
userInput = enhancedEntry(root, 'Enter # of cards:', 'Deal', dealCards)
userInput.pack(fill=X)
# create instance of myButtons without any button inside
displayedButtons = myButtons(root)
displayedButtons.pack()
root.mainloop()