I build on the suggestion by rantingrick, but took it in a bit different direction.
I now have working code that performs reasonable. The reason for the class lines (as opposed to just a function) is b/c font.measure appears not that fast. So I want to remember between different calls to lines.count where the cutoff was, and then start looking from there. This one step of "optimization" was enough to make it run reasonable on my system. There are one important thing skipped, Tkinter.Label takes whitespace into account. This code does not yet. Also I just hacked this together as an example solution to work further from. import Tkinter as Tk import tkFont import random import sys def genstr (j): rno = random.randint(4,50) ret_val = str(j) + ":" for i in range (0, rno): ret_val += "hello" + str(i) return ret_val def gendata (lh): ret_val = [] for i in range(0,lh): ret_val.append (genstr (i)) return ret_val data = gendata (100) root = Tk.Tk() font = tkFont.Font(family='times', size=13) class lines: def __init__ (self): self.lastct = 1 # remember where the cutoff was last work from there def count (self, text, cutoff = 400): global font no_lines = 1 start_idx = 0 idx = self.lastct while True: if idx > len (text): idx = len (text) # shrink from guessed value while font.measure (text[start_idx:idx - 1]) > cutoff: if idx <= start_idx: print "error" sys.exit () else: idx -= 1 self.lastct = idx - start_idx # adjust since was too big # increase from guessed value (note: if first shrunk then done) while (idx < len (text) and font.measure (text[start_idx:idx]) < cutoff): idx += 1 self.lastct = idx - start_idx # adjust since was too small # next line has been determined print "*" + text[start_idx:idx-1] + "*" if idx == len(text) and font.measure (text[start_idx:]) < cutoff: return no_lines elif idx == len(text): return no_lines + 1 else: no_lines += 1 start_idx = idx - 1 idx = start_idx + self.lastct lin = lines() # for testing speed compute for all data for i in range(0,len(data)): lin.count(data[i], 450) # show only first 10 for i in range(0,min(len(data),10)): l = Tk.Label(root) l.pack() l['text'] = data[i] print i no = lin.count (data[i], 450) print "computed lines", no l['width'] = 50 l['justify'] = Tk.LEFT l['anchor'] = 'w' l['wraplength'] = 450 l['padx']=10 l['pady'] = 5 l['height'] = no l['font'] = font if i % 2 == 0: l['background'] = 'grey80' else: l['background'] = 'grey70' root.mainloop() -- http://mail.python.org/mailman/listinfo/python-list