#!/usr/bin/env python import sys import os from Tkinter import * from idlelib.Percolator import Percolator from idlelib.ColorDelegator import ColorDelegator from idlelib.textView import view_file import turtle import time demo_dir = os.getcwd() if "turtleDemo.py" not in os.listdir(demo_dir): print "Directory of turtleDemo must be current working directory!" print "But in your case this is", demo_dir sys.exit() STARTUP = 1 READY = 2 RUNNING = 3 DONE = 4 EVENTDRIVEN = 5 menufont = ("Arial", 12, NORMAL) btnfont = ("Arial", 12, 'bold') txtfont = ('Lucida Console', 8, 'normal') def getExampleEntries(): entries1 = [entry for entry in os.listdir(demo_dir) if entry.startswith("tdemo_") and not entry.endswith(".pyc")] entries2 = [] for entry in entries1: if entry.endswith(".py"): entries2.append(entry) else: path = os.path.join(demo_dir, entry) sys.path.append(path) subdir = [entry] scripts = [script for script in os.listdir(path) if script.startswith("tdemo_") and script.endswith(".py")] entries2.append(subdir+scripts) return entries2 def showDemoHelp(): view_file(demo.root, "Help on turtleDemo", os.path.join(demo_dir, "demohelp.txt")) def showAboutDemo(): view_file(demo.root, "About turtleDemo", os.path.join(demo_dir, "about_turtledemo.txt")) def showAboutTurtle(): view_file(demo.root, "About the new turtle module.", os.path.join(demo_dir, "about_turtle.txt")) class DemoWindow(object): def __init__(self, filename=None): self.root = root = turtle._root = Tk() root.title('Python turtle-graphics examples') root.wm_protocol("WM_DELETE_WINDOW", self._destroy) root.grid_rowconfigure(1, weight=1) root.grid_columnconfigure(0, weight=1) root.grid_columnconfigure(1, minsize=90, weight=1) root.grid_columnconfigure(2, minsize=90, weight=1) root.grid_columnconfigure(3, minsize=90, weight=1) self.mBar = Frame(root, relief=RAISED, borderwidth=2) self.ExamplesBtn = self.makeLoadDemoMenu() self.OptionsBtn = self.makeHelpMenu() self.mBar.tk_menuBar(self.ExamplesBtn, self.OptionsBtn) self.mBar.grid(row=0, columnspan=4, sticky='news') pane = PanedWindow(orient=HORIZONTAL, sashwidth=5, sashrelief=SOLID, bg='#ddd') pane.add(self.makeTextFrame(pane)) pane.add(self.makeGraphFrame(pane)) pane.grid(row=1, columnspan=4, sticky='news') self.output_lbl = Label(root, height= 1, text=" --- ", bg="#ddf", font=("Arial", 16, 'normal'), borderwidth=2, relief=RIDGE) self.start_btn = Button(root, text=" START ", font=btnfont, fg="white", disabledforeground = "#fed", command=self.startDemo) self.stop_btn = Button(root, text=" STOP ", font=btnfont, fg="white", disabledforeground = "#fed", command=self.stopIt) self.clear_btn = Button(root, text=" CLEAR ", font=btnfont, fg="white", disabledforeground="#fed", command = self.clearCanvas) self.output_lbl.grid(row=2, column=0, sticky='news', padx=(0,5)) self.start_btn.grid(row=2, column=1, sticky='ew') self.stop_btn.grid(row=2, column=2, sticky='ew') self.clear_btn.grid(row=2, column=3, sticky='ew') Percolator(self.text).insertfilter(ColorDelegator()) self.dirty = False self.exitflag = False if filename: self.loadfile(filename) self.configGUI(NORMAL, DISABLED, DISABLED, DISABLED, "Choose example from menu", "black") self.state = STARTUP def onResize(self, event): cwidth = self._canvas.winfo_width() cheight = self._canvas.winfo_height() self._canvas.xview_moveto(0.5*(self.canvwidth-cwidth)/self.canvwidth) self._canvas.yview_moveto(0.5*(self.canvheight-cheight)/self.canvheight) def makeTextFrame(self, root): self.text_frame = text_frame = Frame(root) self.text = text = Text(text_frame, name='text', padx=5, wrap='none', width=45) self.vbar = vbar = Scrollbar(text_frame, name='vbar') vbar['command'] = text.yview vbar.pack(side=LEFT, fill=Y) self.hbar = hbar = Scrollbar(text_frame, name='hbar', orient=HORIZONTAL) hbar['command'] = text.xview hbar.pack(side=BOTTOM, fill=X) text['font'] = txtfont text['yscrollcommand'] = vbar.set text['xscrollcommand'] = hbar.set text.pack(side=LEFT, fill=BOTH, expand=1) return text_frame def makeGraphFrame(self, root): turtle._Screen._root = root self.canvwidth = 1000 self.canvheight = 800 turtle._Screen._canvas = self._canvas = canvas = turtle.ScrolledCanvas( root, 800, 600, self.canvwidth, self.canvheight) canvas.adjustScrolls() canvas._rootwindow.bind('', self.onResize) canvas._canvas['borderwidth'] = 0 self.screen = _s_ = turtle.Screen() turtle.TurtleScreen.__init__(_s_, _s_._canvas) self.scanvas = _s_._canvas turtle.RawTurtle.screens = [_s_] return canvas def configGUI(self, menu, start, stop, clear, txt="", color="blue"): self.ExamplesBtn.config(state=menu) self.start_btn.config(state=start) if start==NORMAL: self.start_btn.config(bg="#d00") else: self.start_btn.config(bg="#fca") self.stop_btn.config(state=stop) if stop==NORMAL: self.stop_btn.config(bg="#d00") else: self.stop_btn.config(bg="#fca") self.clear_btn.config(state=clear) self.clear_btn.config(state=clear) if clear==NORMAL: self.clear_btn.config(bg="#d00") else: self.clear_btn.config(bg="#fca") self.output_lbl.config(text=txt, fg=color) def makeLoadDemoMenu(self): CmdBtn = Menubutton(self.mBar, text='Examples', underline=0, font=menufont) CmdBtn.pack(side=LEFT, padx="2m") CmdBtn.menu = Menu(CmdBtn) for entry in getExampleEntries(): def loadexample(x): def emit(): self.loadfile(x) return emit if isinstance(entry,str): CmdBtn.menu.add_command(label=entry[6:-3], underline=0, font=menufont, command=loadexample(entry)) else: _dir, entries = entry[0], entry[1:] CmdBtn.menu.choices = Menu(CmdBtn.menu) for e in entries: CmdBtn.menu.choices.add_command( label=e[6:-3], underline=0, font=menufont, command = loadexample(os.path.join(_dir,e))) CmdBtn.menu.add_cascade( label=_dir[6:], menu = CmdBtn.menu.choices, font=menufont) CmdBtn['menu'] = CmdBtn.menu return CmdBtn def makeHelpMenu(self): CmdBtn = Menubutton(self.mBar, text='Help', underline=0, font = menufont) CmdBtn.pack(side=LEFT, padx='2m') CmdBtn.menu = Menu(CmdBtn) CmdBtn.menu.add_command(label='About turtle.py', font=menufont, command=showAboutTurtle) CmdBtn.menu.add_command(label='turtleDemo - Help', font=menufont, command=showDemoHelp) CmdBtn.menu.add_command(label='About turtleDemo', font=menufont, command=showAboutDemo) CmdBtn['menu'] = CmdBtn.menu return CmdBtn def refreshCanvas(self): if not self.dirty: return self.screen.clear() self.dirty=False def loadfile(self,filename): self.refreshCanvas() if os.path.exists(filename) and not os.path.isdir(filename): # load and display file text f = open(filename,'r') chars = f.read() f.close() self.text.delete("1.0", "end") self.text.insert("1.0",chars) direc, fname = os.path.split(filename) self.root.title(fname[6:-3]+" - a Python turtle graphics example") self.module = __import__(fname[:-3]) reload(self.module) self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED, "Press start button", "red") self.state = READY def startDemo(self): self.refreshCanvas() self.dirty = True turtle.TurtleScreen._RUNNING = True self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED, "demo running...", "black") self.screen.clear() self.screen.mode("standard") self.state = RUNNING try: result = self.module.main() if result == "EVENTLOOP": self.state = EVENTDRIVEN else: self.state = DONE except turtle.Terminator: self.state = DONE result = "stopped!" if self.state == DONE: self.configGUI(NORMAL, NORMAL, DISABLED, NORMAL, result) elif self.state == EVENTDRIVEN: self.exitflag = True self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED, "use mouse/keys or STOP", "red") def clearCanvas(self): self.refreshCanvas() self.scanvas.config(cursor="") self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED) def stopIt(self): if self.exitflag: self.clearCanvas() self.exitflag = False self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED, "STOPPED!", "red") turtle.TurtleScreen._RUNNING = False else: turtle.TurtleScreen._RUNNING = False def _destroy(self): self.root.destroy() sys.exit() if __name__ == '__main__': demo = DemoWindow() RUN = True while RUN: try: print "ENTERING mainloop" demo.root.mainloop() except AttributeError: print "CRASH!!!- WAIT A MOMENT!" time.sleep(0.3) print "GOING ON .." demo.refreshCanvas() ## time.sleep(1) except: RUN = FALSE