class Spacer(Frame): def __init__(self, parent, relief='raised', *args, **kw): apply(Frame.__init__, (self, parent) + args, kw) #self.grid_rowconfigure(0, weight=1) #self.grid_columnconfigure(1, weight=1) self.bg = self.cget('bg') self.relief = relief self.grid_columnconfigure(0, weight=1) self.canvas = Canvas(self, background=self.bg, width=1, height=6) self.canvas.grid(row=0, column=0, sticky=Tkinter.NSEW) #self.canvas.bind('<Configure>', self.resizeCallback) self.grid(sticky=Tkinter.EW) self.canvasL1 = [] self.canvasL2 = [] self.canvasL3 = [] self.refresh = 0 self.event = None self.bind('<Configure>', self.resizeAfter) def resizeAfter(self, event): self.event = event if self.refresh: return else: self.refresh = 1 self.after_idle(lambda: self.resize(self.event)) def resize(self, event): m = 6 w = event.width h = event.height N = int(h / m) self.canvas.config(width=w, height=h) if self.relief == 'sunken': fill1 = 'grey65' fill2 = 'grey95' else: fill1 = 'grey95' fill2 = 'grey65' for i in range(N): y = 1 + (i / float(N)) * h if i >= len(self.canvasL1): rect1 = self.canvas.create_rectangle(4, y + 0, w - 5, y + 2, width=0, fill=fill1) rect2 = self.canvas.create_rectangle(5, y + 1, w - 4, y + 3, width=0, fill=fill2) rect3 = self.canvas.create_rectangle(5, y + 1, w - 5, y + 2, width=0, fill=self.bg) self.canvasL1.append(rect1) self.canvasL2.append(rect2) self.canvasL3.append(rect3) else: self.canvas.coords(self.canvasL1[i], 4, y + 0, w - 5, y + 2) self.canvas.coords(self.canvasL2[i], 5, y + 1, w - 4, y + 3) self.canvas.coords(self.canvasL3[i], 5, y + 1, w - 5, y + 2) if N > len(self.canvasL1): for i in range(N, len(self.canvasL1)): self.canvas.delete(self.canvasL1[i]) self.canvas.delete(self.canvasL2[i]) self.canvas.delete(self.canvasL3[i]) self.refresh = 0
class ProgressBar(BasePopup): def __init__(self, parent, text='', progress=0, total=100, title=None, width=200, height=15, transient=True, *args, **kw): self.progress = float(progress) self.cWidth = width self.cHeight = height self.total = float(total) or 1.0 self.text = text BasePopup.__init__(self, parent=parent, title=title or 'Progress Bar', transient=transient, *args, **kw) def body(self, parent): self.bw = 2 # borderwidth width = self.cWidth + self.bw height = self.cHeight + self.bw self.label = Label(parent, text=self.text) self.label.grid(row=0, column=0, sticky=Tkinter.W) self.percent = Label(parent, text=' %') self.percent.grid(row=0, column=2, sticky=Tkinter.W) self.canvas = Canvas(parent, background='grey70', width=width, height=height) self.canvas.grid(row=0, column=1, sticky=Tkinter.W) self.canvas.create_rectangle(0, 0, width, height, outline='black', width=self.bw) self.bar = self.canvas.create_rectangle(self.bw, self.bw, self.bw, self.cHeight, outline='#B05848', fill='#B05848', width=self.bw) self.update() def update(self): p = self.progress / self.total width = int(self.cWidth * p) self.canvas.coords(self.bar, self.bw, self.bw, width, self.cHeight) self.percent.set(' %3.1d' % int(100 * p) + "%") self.label.set(self.text) self.update_idletasks() if self.progress == self.total: time.sleep(0.1) self.close() def increment(self, n=1): p = self.progress + n self.progress = max(min(self.total, p), 0) self.update() def get(self): return self.progress / self.total def set(self, value): if value <= 1: self.progress = float(value) * self.total elif value <= self.total: self.progress = float(value) else: raise 'Cannot set to a value exceeding the total' self.update() def setText(self, text=''): self.text = text self.label.set(self.text)
class CrossLine(Frame): def __init__(self, parent, color='black', side='both', canvas_bg='lightgrey', *args, **kw): self.color = color self.side = side apply(Frame.__init__, (self, parent) + args, kw) #self.grid_rowconfigure(0, weight=1) #self.grid_columnconfigure(1, weight=1) fill = Tkinter.X w = kw.get('width', 1) z = h = kw.get('height', 1) #self.canvas.config(height=h) self.canvas = Canvas(self, width=w, height=h, background=canvas_bg) self.cross = {'upper': [], 'lower': [], 'both': []} # # This is setup only... coordinates do not matter here # if self.side in ['both', 'upper']: self.cross['upper'].append( self.canvas.create_line(0, 0, 0, 0, fill=color)) self.cross['upper'].append( self.canvas.create_line(0, 0, 0, 0, fill=color)) self.cross['both'].append( self.canvas.create_line(0, 0, 0, 0, fill=color)) if self.side in ['both', 'lower']: self.cross['lower'].append( self.canvas.create_line(0, 0, 0, 0, fill=color)) self.cross['lower'].append( self.canvas.create_line(0, 0, 0, 0, fill=color)) self.canvas.pack(expand=Tkinter.YES, fill=fill) #self.canvas.bind('<Configure>', self.resizeCallback) self.bind('<Configure>', self.resizeCallback) def resizeCallback(self, event): self.update_idletasks() #w = self.canvas.winfo_width() #h = self.canvas.winfo_height() w = self.winfo_width() h = self.winfo_height() if self.side == 'both': mh = h / 2 elif self.side == 'lower': mh = 0 else: mh = h if self.side in ['both', 'upper']: self.canvas.coords(self.cross['upper'][0], 0, 0, w / 3, mh) self.canvas.coords(self.cross['upper'][1], w * 2 / 3, mh, w, 0) self.canvas.coords(self.cross['both'][0], w / 3, mh, w * 2 / 3, mh) if self.side in ['both', 'lower']: self.canvas.coords(self.cross['lower'][0], 0, h, w / 3, mh) self.canvas.coords(self.cross['lower'][1], w * 2 / 3, mh, w, h) # color is a tuple def setColor(self, color): (r, g, b) = color self.canvas.itemconfig(self.item, fill=hexRepr(r, g, b))
class ToggleArrow(Frame): def __init__(self, parent, arrowSize=11, outline='#5050b0', fill='#a0a0ff', isArrowClosed=True, callback=None, *args, **kw): self.arrowSize = arrowSize self.isArrowClosed = isArrowClosed self.callback = callback apply(Frame.__init__, (self, parent) + args, kw) bg = kw.get('bg') if (not bg): bg = kw.get('background') if (not bg): bg = parent.cget('bg') # below does not work for some reason, instead explicitly create rectangle below #self.canvas = Canvas(self, width=arrowSize, height=arrowSize, bg=bg) self.canvas = Canvas(self, width=arrowSize + 3, height=arrowSize + 1) self.canvas.grid(row=0, column=0) # need +/-1 otherwise get line along borders self.canvas.create_rectangle(-1, -1, arrowSize + 3, arrowSize + 1, fill=bg) # arbitrary coords self.arrow = self.canvas.create_polygon(0, 0, 1, 0, 1, 1, fill=fill, outline=outline) self.drawArrow() self.canvas.bind('<Button-1>', self.flipState) def drawArrow(self): s = self.arrowSize if (self.isArrowClosed): self.canvas.coords(self.arrow, 2, 0, s + 2, s / 2, 2, s) else: self.canvas.coords(self.arrow, 2, 0, s + 2, 0, (s / 2) + 2, s) def flipState(self, *event): self.isArrowClosed = not self.isArrowClosed if (self.callback): self.callback(self.isArrowClosed) self.drawArrow()