methodtwo Apprentice
Joined: 01 Feb 2008 Posts: 231
|
Posted: Tue Jan 14, 2014 3:55 pm Post subject: python tkinter LIFE gui questions |
|
|
Hi
I've written a Python TkinterGui for a version of conway's LIFE. It's not a fully-fledged "laboratory" just a Gui that displays games from coded initial "configurations" for N generations. I have a version working, but this version relies on a super-class and i don't understand why my attempts to have it not rely on this super-class(and just be a sub-class of Frame) don't work.
Here is my attempt to have it just be a sub-class of Frame(and not rely on the external Gui super-class):
Please ignore the way the the indentation is wrong. I don't know why this forum software is displaying it like that. It isn't displayed like that in the text box i'm typing this into. There are no indentation errors in this code when i view it(in Vim) and run it
Code: | #!/usr/bin/env python
from collections import Counter
import random, sys, time
from Tkinter import *
from tkMessageBox import showinfo, askyesno
from guimaker import GuiMakerWindowMenu
Fontsz = 15 # defaults if no constructor args
class LifeBase(Frame): # a kind of Frame
def __init__(self, parent=None,
fg='white', bg='black', fontsz=Fontsz,
degree=100):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH)
self.master.title(Life 0.1)
self.degree = degree
self.label = {}
self.makeWidgets = (lambda s=self, f=fg, b=bg, fs=fontsz:
s.drawBoard(f, b, fs))
blinker = {(1, 0), (1, 1), (1, 2)}
block = {(0, 0), (1, 1), (0, 1), (1, 0)}
toad = {(1, 2), (0, 1), (0, 0), (0, 2), (1, 3), (1, 1)}
glider = {(0, 1), (1, 0), (0, 0), (0, 2), (2, 1)}
world = (block | self.offset(blinker, (5, 2)) | self.offset(glider, (15, 5)) |
self.offset(toad, (15, 12)) |{(4, 20), (5, 20), (6, 20), (7, 20)} |
self.offset(block, (2, 15)))
self.neighboring_cells = [(-1, -1), (-1, 0), (-1, 1),
( 0, -1), ( 0, 1),
( 1, -1), ( 1, 0), ( 1, 1)]
xs, ys = zip(*world)
self.life(world, 30)
def drawBoard(self, fg, bg, fontsz):
for i in range(self.degree):
frm = Frame(self)
frm.pack(expand=YES, fill=BOTH)
for j in range(self.degree):
widget = Label(frm, fg=fg, bg=bg,
text=' ', font=('courier', fontsz, 'bold'),
relief=SUNKEN, bd=4, padx=10, pady=10)
widget.pack(side=LEFT, expand=YES, fill=BOTH)
self.label[(i, j)] = widget
def life(self,world, N):
"Play Conway's game of life for N generations from initial world."
for g in range(N+1):
self.display(world, g)
counts = Counter(n for c in world for n in self.offset(self.neighboring_cells, c))
world = set(c for c in counts if counts[c] == 3
or counts[c] == 2 and c in world)
return world
def offset(self,world, delta):
"Slide/offset all the cells in world by delta, a (dx, dy) vector."
(dx, dy) = delta
return set((x+dx, y+dy) for (x, y) in world)
def display(self,world, g):
"Display the world as a grid of characters."
print ' GENERATION {}:'.format(g)
for x in range(self.degree):
for y in range(self.degree):
if (x, y) in world:
labelx = self.label[(x, y)]
labelx.config(bg="black")
for x in range(self.degree):
for y in range(self.degree):
if(x, y) in world:
print '(X, Y) %d,%d is in world' % (x,y)
labelx = self.label[(x, y)]
labelx.config(bg="purple")
self.update()
if __name__=='__main__':
root = Tk()
LifeBase(root).mainloop()
#End of Life_0.1_alt.py |
Why does this Gui version not work, coded as above? What do i need to do to get it to work as a subclass of Frame, or just a standalone class. I've tried having self.label as a global(module scope) dictionary. I've tried having LifeBase as a standalone class. When it's coded as above i get a KeyError(0, 0) the first time i do:
Code: | labelx = self.label[(x, y)] |
Getting this error seems to be the closest it comes to running! . I just want it to run without need for an explicitly coded super-class
Thank you very much for any help |
|