K
Kim Petersen
I've worked on this table object a bit too long - and seem to have
stared too long at the code. Can someone see where it goes wrong in
the insertrow function?
Also optimization hints and alternatives will be greatly appreciated.
<code>
#!env python
#
# created: "15:19 20/01-2004" by Kim Petersen <[email protected]>
#
# $Id$
#
import Tkinter
class UserDict:
defaults={}
def __init__(self,inherit=None):
if not inherit:
self.inherit=[]
else:
self.inherit=inherit
self.dict=self.defaults.copy()
def __setitem__(self,name,value): self.dict[name]=value
def __getitem__(self,name):
if not self.dict.has_key(name):
for dict in self.inherit:
if dict.has_key(name):
return dict[name]
raise KeyError,"%s not found" % (name,)
return self.dict[name]
def haskey(self,name): return self.dict.has_key(name)
class Cell(UserDict):
defaults={"width": 0,"height": 0,"text": '',"color": "black","background": "white",
"widgets": None}
def __init__(self,master,row,column,text):
UserDict.__init__(self,[row,column])
self.master=master
self["text"]=text
self.row=row # these are needed for us to find the actual row/col
self.column=column
self.create()
def create(self):
"""Create the widgets the first time (might inflict up to two resize's)"""
x,y=self.column["x"],self.row["y"]
w,h=self.column["width"],self.row["height"]
r=self.master.create_rectangle((x,y,x+w,y+h),fill=self["background"])
t=self.master.create_text((x+self.master.colpadding,y+h/2),
text=self["text"],
anchor="w",fill=self["color"])
self["widgets"]=[r,t]
bbox=self.master.bbox(t)
self["width"]=bbox[2]-bbox[0]
self["height"]=bbox[3]-bbox[1]
if self["width"]+self.master.colpadding*2>w:
self.column.resize(self["width"]+self.master.colpadding*2)
self.resize()
if self["height"]+self.master.rowpadding*2>h:
self.row.resize(self["height"]+self.master.rowpadding*2)
self.resize()
def resize(self):
"""Resize according to the width/height given by row,column"""
x,y=self.column["x"],self.row["y"]
w,h=self.column["width"],self.row["height"]
self.master.coords(self["widgets"][0],(x,y,x+w,y+h))
self.master.coords(self["widgets"][1],(x+self.master.colpadding,y+h/2))
def move(self,dx,dy):
"""Relatively move according to delta's"""
self.master.move(self["widgets"][0],dx,dy)
self.master.move(self["widgets"][1],dx,dy)
class Column(UserDict):
""" """
defaults={"x": 0,"width": 0,"label": '',"tag": ''}
def __init__(self,master,label='',before=None):
UserDict.__init__(self)
self.master=master
if master.columns:
if not before or before>0:
if not before:
after=(-1)
else:
after=before-1
self.dict["x"]=master.columns[after]["x"]+master.columns[after]["width"]
# since we have a width of 0 there is no need to move the rest of the columns.
def calcwidth(self):
"""Calculate the *actually* needed width of the column (*not* the current one)."""
width=0
for row in self.master.rows:
width=max(self.master.cells[(row,self)]["width"],width)
return width+self.master.colpadding*2
def resize(self,width):
# calc delta, set new width
dx=width-self["width"]
self["width"]=width
ci=self.master.columns.index(self)
# resize the cells
for row in self.master.rows:
try:
self.master.cells[(row,self)].resize()
except KeyError:
pass
# move columns to the right further to the right
for i in range(ci+1,len(self.master.columns)):
self.master.columns.move(dx)
def move(self,dx):
self["x"]=self["x"]+dx
# move the cells correspondingly
for row in self.master.rows:
try:
self.master.cells[(row,self)].move(dx,0)
except KeyError:
pass
class Row(UserDict):
defaults={"y": 0,"height": 0,"label": '',"tag": ''}
def __init__(self,master,label,before=None):
UserDict.__init__(self)
self["label"]=label
# now insert it.
self.master=master
if master.rows:
if not before or before>0:
if not before:
after=(-1)
else:
after=before-1
self.dict["y"]=master.rows[after]["y"]+master.rows[after]["height"]
def calcheight(self):
"""Calculate the *actually* needed width of the column (*not* the current one)."""
height=0
for row in self.master.columns:
height=max(self.master.cells[(self,column)]["height"],height)
return height+self.master.rowpadding*2
def resize(self,height):
dy=height-self.dict["height"]
self.dict["height"]=height
ri=self.master.rows.index(self)
for column in self.master.columns:
if self.master.cells.has_key((self,column)):
self.master.cells[(self,column)].resize()
for i in range(ri+1,len(self.master.rows)):
self.master.rows.move(dy)
def move(self,dy):
self.dict["y"]=self.dict["y"]+dy
for col in self.master.columns:
try:
self.master.cells[(self,col)].move(0,dy)
except KeyError:
pass
pass
def moveto(self,y):
self.move(y-self.dict["y"])
def __setitem__(self,name,value):
if name=="height":
self.resize(value)
elif name=="y":
self.move(value-self["y"])
else:
self.dict[name]=value
class Table(Tkinter.Canvas):
"""A table object - it consists of a number of cells layed out in rows and columns
A row has a specific height
A row can have a label
A column has a specific width
A column can have a label
"""
def __init__(self,master,**args):
Tkinter.Canvas.__init__(self,master,**args)
self.colpadding=2
self.rowpadding=2
self.columns=[] # each item contains data about the column
self.rows=[] # each item contains data about the row
self.cells={} # index: (row,col)
def insertrow(self,pos,values):
self.rows[pos
os]=[Row(self,'',pos)]
row=self.rows[pos]
for i in range(len(values)):
if i<len(self.columns):
col=self.columns
else:
self.columns.append(Column(self,''))
col=self.columns[-1]
self.cells[(row,col)]=Cell(self,row,col,values)
def row_add(self,values):
self.rows.append(Row(self,''))
row=self.rows[-1]
for i in range(len(values)):
if i<len(self.columns):
col=self.columns
else:
self.columns.append(Column(self,''))
col=self.columns[-1]
self.cells[(row,col)]=Cell(self,row,col,values)
if __name__=="__main__":
tk=Tkinter.Tk()
tk.grid_rowconfigure(1,weight=1)
tk.grid_columnconfigure(1,weight=1)
tk.wm_geometry("800x1150+0+0")
table=Table(tk)
table.grid(row=1,column=1,sticky="nsew")
for line in open("/etc/passwd","r"):
values=unicode(line.strip(),"iso8859-1").split(":")
#tk.update()
#table.insertrow(0,values)
table.row_add(values)
for row in table.rows:
print row["y"],row["height"]
tk.mainloop()
# Local Variables:
# tab-width: 3
# py-indent-offset: 3
# End:
</code>
stared too long at the code. Can someone see where it goes wrong in
the insertrow function?
Also optimization hints and alternatives will be greatly appreciated.
<code>
#!env python
#
# created: "15:19 20/01-2004" by Kim Petersen <[email protected]>
#
# $Id$
#
import Tkinter
class UserDict:
defaults={}
def __init__(self,inherit=None):
if not inherit:
self.inherit=[]
else:
self.inherit=inherit
self.dict=self.defaults.copy()
def __setitem__(self,name,value): self.dict[name]=value
def __getitem__(self,name):
if not self.dict.has_key(name):
for dict in self.inherit:
if dict.has_key(name):
return dict[name]
raise KeyError,"%s not found" % (name,)
return self.dict[name]
def haskey(self,name): return self.dict.has_key(name)
class Cell(UserDict):
defaults={"width": 0,"height": 0,"text": '',"color": "black","background": "white",
"widgets": None}
def __init__(self,master,row,column,text):
UserDict.__init__(self,[row,column])
self.master=master
self["text"]=text
self.row=row # these are needed for us to find the actual row/col
self.column=column
self.create()
def create(self):
"""Create the widgets the first time (might inflict up to two resize's)"""
x,y=self.column["x"],self.row["y"]
w,h=self.column["width"],self.row["height"]
r=self.master.create_rectangle((x,y,x+w,y+h),fill=self["background"])
t=self.master.create_text((x+self.master.colpadding,y+h/2),
text=self["text"],
anchor="w",fill=self["color"])
self["widgets"]=[r,t]
bbox=self.master.bbox(t)
self["width"]=bbox[2]-bbox[0]
self["height"]=bbox[3]-bbox[1]
if self["width"]+self.master.colpadding*2>w:
self.column.resize(self["width"]+self.master.colpadding*2)
self.resize()
if self["height"]+self.master.rowpadding*2>h:
self.row.resize(self["height"]+self.master.rowpadding*2)
self.resize()
def resize(self):
"""Resize according to the width/height given by row,column"""
x,y=self.column["x"],self.row["y"]
w,h=self.column["width"],self.row["height"]
self.master.coords(self["widgets"][0],(x,y,x+w,y+h))
self.master.coords(self["widgets"][1],(x+self.master.colpadding,y+h/2))
def move(self,dx,dy):
"""Relatively move according to delta's"""
self.master.move(self["widgets"][0],dx,dy)
self.master.move(self["widgets"][1],dx,dy)
class Column(UserDict):
""" """
defaults={"x": 0,"width": 0,"label": '',"tag": ''}
def __init__(self,master,label='',before=None):
UserDict.__init__(self)
self.master=master
if master.columns:
if not before or before>0:
if not before:
after=(-1)
else:
after=before-1
self.dict["x"]=master.columns[after]["x"]+master.columns[after]["width"]
# since we have a width of 0 there is no need to move the rest of the columns.
def calcwidth(self):
"""Calculate the *actually* needed width of the column (*not* the current one)."""
width=0
for row in self.master.rows:
width=max(self.master.cells[(row,self)]["width"],width)
return width+self.master.colpadding*2
def resize(self,width):
# calc delta, set new width
dx=width-self["width"]
self["width"]=width
ci=self.master.columns.index(self)
# resize the cells
for row in self.master.rows:
try:
self.master.cells[(row,self)].resize()
except KeyError:
pass
# move columns to the right further to the right
for i in range(ci+1,len(self.master.columns)):
self.master.columns.move(dx)
def move(self,dx):
self["x"]=self["x"]+dx
# move the cells correspondingly
for row in self.master.rows:
try:
self.master.cells[(row,self)].move(dx,0)
except KeyError:
pass
class Row(UserDict):
defaults={"y": 0,"height": 0,"label": '',"tag": ''}
def __init__(self,master,label,before=None):
UserDict.__init__(self)
self["label"]=label
# now insert it.
self.master=master
if master.rows:
if not before or before>0:
if not before:
after=(-1)
else:
after=before-1
self.dict["y"]=master.rows[after]["y"]+master.rows[after]["height"]
def calcheight(self):
"""Calculate the *actually* needed width of the column (*not* the current one)."""
height=0
for row in self.master.columns:
height=max(self.master.cells[(self,column)]["height"],height)
return height+self.master.rowpadding*2
def resize(self,height):
dy=height-self.dict["height"]
self.dict["height"]=height
ri=self.master.rows.index(self)
for column in self.master.columns:
if self.master.cells.has_key((self,column)):
self.master.cells[(self,column)].resize()
for i in range(ri+1,len(self.master.rows)):
self.master.rows.move(dy)
def move(self,dy):
self.dict["y"]=self.dict["y"]+dy
for col in self.master.columns:
try:
self.master.cells[(self,col)].move(0,dy)
except KeyError:
pass
pass
def moveto(self,y):
self.move(y-self.dict["y"])
def __setitem__(self,name,value):
if name=="height":
self.resize(value)
elif name=="y":
self.move(value-self["y"])
else:
self.dict[name]=value
class Table(Tkinter.Canvas):
"""A table object - it consists of a number of cells layed out in rows and columns
A row has a specific height
A row can have a label
A column has a specific width
A column can have a label
"""
def __init__(self,master,**args):
Tkinter.Canvas.__init__(self,master,**args)
self.colpadding=2
self.rowpadding=2
self.columns=[] # each item contains data about the column
self.rows=[] # each item contains data about the row
self.cells={} # index: (row,col)
def insertrow(self,pos,values):
self.rows[pos
row=self.rows[pos]
for i in range(len(values)):
if i<len(self.columns):
col=self.columns
else:
self.columns.append(Column(self,''))
col=self.columns[-1]
self.cells[(row,col)]=Cell(self,row,col,values)
def row_add(self,values):
self.rows.append(Row(self,''))
row=self.rows[-1]
for i in range(len(values)):
if i<len(self.columns):
col=self.columns
else:
self.columns.append(Column(self,''))
col=self.columns[-1]
self.cells[(row,col)]=Cell(self,row,col,values)
if __name__=="__main__":
tk=Tkinter.Tk()
tk.grid_rowconfigure(1,weight=1)
tk.grid_columnconfigure(1,weight=1)
tk.wm_geometry("800x1150+0+0")
table=Table(tk)
table.grid(row=1,column=1,sticky="nsew")
for line in open("/etc/passwd","r"):
values=unicode(line.strip(),"iso8859-1").split(":")
#tk.update()
#table.insertrow(0,values)
table.row_add(values)
for row in table.rows:
print row["y"],row["height"]
tk.mainloop()
# Local Variables:
# tab-width: 3
# py-indent-offset: 3
# End:
</code>