Help and optimization hints, anyone?

Kim Petersen kim at lignus.dk
Fri Jan 23 11:41:37 CET 2004


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 <kim at vindinggaard.dk>
#
# $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[i].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[i].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:pos]=[Row(self,'',pos)]
      row=self.rows[pos]
      for i in range(len(values)):
         if i<len(self.columns):
            col=self.columns[i]
         else:
            self.columns.append(Column(self,''))
            col=self.columns[-1]
         self.cells[(row,col)]=Cell(self,row,col,values[i])

   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[i]
         else:
            self.columns.append(Column(self,''))
            col=self.columns[-1]
         self.cells[(row,col)]=Cell(self,row,col,values[i])

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>
-- 
Privat  ==========================  Kim Petersen  ====================  Arbejde
Email kim at vindinggaard.dk  =====  Jens Grøns Vej 11  =====  Email kim at lignus.dk
Tlf +45 75 83 15 50  ==============  7100 Vejle  =========  Tlf +45 75 83 15 51
Fax +45 75 83 15 62  =============  DK - Danmark  ========  Fax +45 75 83 15 62





More information about the Python-list mailing list