Hi all,
I know there have been several threads about getting card images into a GUI, but I'm flustered trying to understand why some things work and some things don't. Here's the code:
import random
from Tkinter import *
import Image, ImageTk
class Card(object):
suits = ["C","D","H","S"]
values = ['A','2','3','4','5','6','7','8','9','T','J','Q','K']
down_img = PhotoImage(file="Deck1.gif")
cards = [x+y for x in suits for y in values]
pics = {}
for x in cards:
pics[x] = PhotoImage(file=x+'.gif')
def __init__(self, suit=None, value=None, up=True):
if suit in Card.suits:
self.suit = suit
else:
self.suit = random.choice(Card.suits)
if value in Card.values:
self.value = value
else:
self.value = random.choice(Card.values)
self.up = up
def __str__(self):
return self.value+self.suit
def picURL(self):
return Card.pics[self.suit+self.value]
def display(self, x,y,angle,canvas):
if self.up:
canvas.create_image(x,y,Card.pics[self.suit+self.value])
else:
canvas.create_image(x,y,Card.down_image)
class Deck(Card):
deck = Card.cards[:]
def __init__(self, suit=None, value=None, up=True):
card = str(suit)+str(value)
if card not in Deck.deck:
if Deck.deck == []:
raise ValueError, "Deck empty!"
card = random.choice(Deck.deck)
suit=card[0]
value=card[1:]
Deck.deck.remove(card)
self.suit = suit
self.value = value
self.up = up
@staticmethod
def shuffle():
Deck.deck = Card.cards
class BridgeRound(Frame):
# display_data contains display info for each hand:
#(startx, starty, dx, dy, angle of rotation)
display_data = [(30,0,10,0,0), \
(200, 30, 0, 10, 270), \
(170, 200, -10, 0, 180), \
(0, 170, 0, -10, 90)]
def __init__(self, master):
Frame.__init__(self,master)
self.canvas = Canvas(self)
self.canvas.grid()
self.grid()
self.deal()
self.display()
def deal(self):
Deck.shuffle()
self.hands = [[Deck() for i in range(13)] for j in range(4)]
def display(self):
for i in range(4):
hand = self.hands[i]
x, y, dx, dy, angle = BridgeRound.display_data[i]
for j in hand:
print j,
j.display(self.canvas,x,y,angle)
x += dx
y += dy
mainw = Tk()
mainw.f = BridgeRound(mainw)
mainw.mainloop()
You may ask, why does he create the images in the Card class? Isn't that wasteful of memory? Well, yes. BUT...for some reason, if I don't maintain a static reference to the card images, they don't display. Thus, a line like
canvas.create_image(PhotoImage(file="H6.gif"))
results in a blank image. So if I want to display all the cards at once, then I have to maintain them all in a data structure.
Anyways, when I run the code, I get
>>>
Traceback (most recent call last):
File "C:\Python24\src\cards\cards.py", line 5, in -toplevel-
class Card(object):
File "C:\Python24\src\cards\cards.py", line 14, in Card
pics[x] = PhotoImage(file=x+'.gif')
File "C:\Python24\lib\lib-tk\Tkinter.py", line 3203, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "C:\Python24\lib\lib-tk\Tkinter.py", line 3144, in __init__
raise RuntimeError, 'Too early to create image'
RuntimeError: Too early to create image
to which I say ?!@#*^$#^?!
So when's the best time to create an image?! I'm sure I can tweak the code to make it run ... but what's the underlying theory about Tkinter images here?
Thanks,
Jeff