# we need a root window object and then a Canvas window object (child) # in order to be able to draw points and lines. # The Point and Line draw() method will use this canvas. # # A Canvas Window on which we can draw points, lines, rectangles, etc. # See the Tkinter module, Canvas class, for more details. # PyScripter may not handle Tkinter well, so to run this example, # use the command line: # python prog.py import Tkinter class XCanvas(Tkinter.Canvas): def __init__(self, rootwin, **kwargs): width = kwargs.get("width", 1000) height = kwargs.get("height", 600) bg = kwargs.get("bg", "white") scrollbars = kwargs.get("scrollbars", True) scalewidget = kwargs.get("scalewidget", True) x_axis = kwargs.get("x_axis", 7) y_axis = kwargs.get("y_axis", 7) self.region = (-50, -50, width, height) self.rootwin = rootwin self.rootframe = Tkinter.Frame(rootwin, width=width, height=height, bg=bg) self.rootframe.pack(expand=True, fill=Tkinter.BOTH) Tkinter.Canvas.__init__(self, self.rootframe, width=width, height=height, bg=bg, scrollregion=self.region) self.config(highlightthickness=0) if scrollbars: self.scrollbars() self.pack(side = Tkinter.LEFT, expand = True, fill = Tkinter.BOTH) # Scale Widget component self.scalewidget = Tkinter.Scale(self.rootframe, from_=1, to=3000, length=500, orient=Tkinter.VERTICAL, font="Consolas 6", command=self.resize) self.scalewidget.set(100) if scalewidget: self.scalewidget.pack(side=Tkinter.TOP, fill=Tkinter.Y, expand=False) else: # place the scale widget far away so we cannot see it on a normal display (1920x1600) self.scalewidget.place(x=100000, y=100000) #x1,y1,x2,y2 = self.bbox('all') #self.xview_scroll(-x2, "units") #self.yview_scroll(-y2, "units") self.xview_moveto(0) self.yview_moveto(0) #self.rootframe.focus_set() if x_axis or y_axis: self.draw_axis(x_axis, y_axis) self.bindings() def scrollbars(self): self.sbarV = Tkinter.Scrollbar(self.rootframe, orient = Tkinter.VERTICAL) self.sbarH = Tkinter.Scrollbar(self.rootframe, orient = Tkinter.HORIZONTAL) self.sbarV.config(command = self.yview) self.sbarH.config(command = self.xview) self.config(yscrollcommand = self.sbarV.set) self.config(xscrollcommand = self.sbarH.set) self.sbarV.pack(side = Tkinter.RIGHT, fill = Tkinter.Y) self.sbarH.pack(side = Tkinter.BOTTOM, fill = Tkinter.X) def bindings(self): self.rootwin.bind("", self.onCtrlMouseWheel) self.rootwin.bind("", self.onAltMouseWheel) self.rootwin.bind("", self.onMouseWheel) self.rootwin.bind("", self.onShiftMouseWheel) self.rootwin.bind("f", self.fit_canvas) self.rootwin.bind("", self.fit_canvas) self.rootwin.bind("", self.onArrowUp) self.rootwin.bind("", self.onArrowDown) self.rootwin.bind("", self.onArrowLeft) self.rootwin.bind("", self.onArrowRight) self.rootwin.bind("", self.onArrowUp) self.rootwin.bind("", self.onArrowDown) self.rootwin.bind("", self.onPrior) self.rootwin.bind("", self.onNext) #self.rootwin.bind("all", self.eventEcho) def show(self, force=False): if force or not self.winfo_ismapped(): self.rootwin.iconify() self.rootwin.update() self.rootwin.deiconify() self.rootwin.lift() #self.rootwin.mainloop() #Tkinter.mainloop() def hide(self): self.rootwin.iconify() def resize(self, percent): x1,y1,x2,y2 = self.region canvas_breadth = max(x2-x1, y2-y1) _region = self.config('scrollregion')[4] region = tuple(float(x) for x in _region) x1,y1,x2,y2 = region breadth = max(x2-x1, y2-y1) if breadth == 0: return r = float(percent) / 100 if r < 0.01 or r > 30: return s = r / (float(breadth) / canvas_breadth) self.scale('all', 0, 0, s, s) nregion = tuple(x*r for x in self.region) self.config(scrollregion=nregion) #------------ Key bindings ------------- def onCtrlMouseWheel(self, event): s = self.scalewidget.get() if event.delta > 0: s += 15 else: s -= 15 self.scalewidget.set(s) def onAltMouseWheel(self, event): s = self.scalewidget.get() if event.delta > 0: s += 5 else: s -= 5 self.scalewidget.set(s) def onMouseWheel(self, event): self.yview_scroll(-1*(event.delta/120), "units") def onArrowUp(self, event): if event.keysym == "Up": self.yview_scroll(-1, "units") else: self.yview_scroll(-1, "pages") def onArrowDown(self, event): if event.keysym == "Down": self.yview_scroll(1, "units") else: self.yview_scroll(1, "pages") def onArrowLeft(self, event): self.xview_scroll(-1, "units") def onArrowRight(self, event): #print event.keysym self.xview_scroll(1, "units") def onPrior(self, event): self.xview_scroll(1, "pages") def onNext(self, event): #print event.keysym self.xview_scroll(-1, "pages") def onShiftMouseWheel(self, event): self.xview_scroll(-1*(event.delta/120), "units") def fit_canvas(self, event): print event.keysym self.scalewidget.set(100) def draw_axis(self, m, n): self.create_line(-40, 0, 100*m, 0, width=1, fill='black', arrow='last') self.create_line(0, -40, 0, 100*n, width=1, fill='black', arrow='last') for i in range(1,m): self.create_line(100*i, -5, 100*i, 0, width=1, fill='black') self.create_text(100*i, -5, text=str(100*i), font='Consolas 8', anchor='s') for i in range(1,n): self.create_line(-5, 100*i, 0, 100*i, width=1, fill='black') self.create_text(-7, 100*i, text=str(100*i), font='Consolas 8', anchor='e') def eventEcho(self, event): print event.keysym #-------------------------------------------------------------------------------------- def test1(): # This is where we create the canvas rootwin1 = Tkinter.Tk() c1 = XCanvas(rootwin1, width=1000, height=800, bg="white") c1.create_rectangle(100, 120, 400, 230, width=2, outline='blue', fill='yellow') c1.create_rectangle(400, 320, 600, 530, width=2, outline='blue', fill='yellow') c1.create_oval(400, 320, 600, 530, width=2, outline='blue', fill='cyan') c1.create_line(200, 50, 500, 430, width=3, fill='blue') #print c1['scrollregion'] rootwin2 = Tkinter.Tk() c2 = XCanvas(rootwin2, scrollbars=False, scalewidget=False, x_axis=0, y_axis=0, width=1000, height=800, bg="cornsilk") c2.create_rectangle(100, 120, 400, 230, width=2, outline='red', fill='yellow') c2.create_oval(100, 120, 400, 230, width=2, outline='red', fill='cyan') c2.create_rectangle(400, 320, 600, 530, width=2, outline='red', fill='yellow') c2.create_line(200, 50, 500, 430, width=3, fill='red') #c1.show() #c2.show() #show_graphics() Tkinter.mainloop() if __name__ == "__main__": test1()