def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.parent.title("L System Equations Rendering Tool for Tkinter") ### variables ### self.iterations = tk.StringVar() self.angle = tk.StringVar() self.axiom = tk.StringVar() self.rule1 = tk.StringVar() self.rule2 = tk.StringVar() self.rule3 = tk.StringVar() self.rule4 = tk.StringVar() self.constants = tk.StringVar() self.status_text = tk.StringVar() if _pil_available: self.status_text.set("Using PIL for rendering") else: self.status_text.set("Using tk Canvas for rendering") self.color1 = "#000000" self.color2 = "#dd0000" self.color3 = "#00dd00" self.color4 = "#0000dd" self.lsf_dir = expanduser(join("~", "lsf-files")) if not isdir(self.lsf_dir): makedirs(self.lsf_dir) self.example_dir = join(dirname(__file__), "examples") self.entries = tk.Frame(self) self.entries.grid(row=0, column=0, sticky=tk.N) ### Labels ### tk.Label(self.entries, text="Settings", font="Helvetica 14 bold").grid(column=0, row=0, sticky=tk.W) tk.Label(self.entries, text="Iterations").grid(column=0, row=1, padx=5, pady=5) tk.Label(self.entries, text="angle").grid(column=0, row=2, padx=5, pady=5) tk.Label(self.entries, text="axiom").grid(column=0, row=3, padx=5, pady=5) tk.Label(self.entries, text="rule1").grid(column=0, row=4, padx=5, pady=5) tk.Label(self.entries, text="rule2").grid(column=0, row=5, padx=5, pady=5) tk.Label(self.entries, text="rule3").grid(column=0, row=6, padx=5, pady=5) tk.Label(self.entries, text="rule4").grid(column=0, row=7, padx=5, pady=5) tk.Label(self.entries, text="constants").grid(column=0, row=8, padx=5, pady=5) tk.Label(self.entries, text="Color Values", font="Helvetica 14 bold").grid(column=0, row=9, padx=5, pady=5) tk.Label(self.entries, text="default (color 1):").grid(column=0, row=10, padx=5, pady=5) tk.Label(self.entries, text="color 2:").grid(column=0, row=11, padx=5, pady=5) tk.Label(self.entries, text="color 3:").grid(column=0, row=12, padx=5, pady=5) tk.Label(self.entries, text="color 4:").grid(column=0, row=13, padx=5, pady=5) ### Entries ### tk.Entry(self.entries, textvariable=self.iterations).grid(column=1, row=1) tk.Entry(self.entries, textvariable=self.angle).grid(column=1, row=2) tk.Entry(self.entries, textvariable=self.axiom).grid(column=1, row=3) tk.Entry(self.entries, textvariable=self.rule1).grid(column=1, row=4) tk.Entry(self.entries, textvariable=self.rule2).grid(column=1, row=5) tk.Entry(self.entries, textvariable=self.rule3).grid(column=1, row=6) tk.Entry(self.entries, textvariable=self.rule4).grid(column=1, row=7) tk.Entry(self.entries, textvariable=self.constants).grid(column=1, row=8) ## Color settings self.c1_label = tk.Label(self.entries, text=self.color1, bg=self.color1) self.c2_label = tk.Label(self.entries, text=self.color2, bg=self.color2) self.c3_label = tk.Label(self.entries, text=self.color3, bg=self.color3) self.c4_label = tk.Label(self.entries, text=self.color4, bg=self.color4) self.c1_label.grid(column=1, row=10) self.c2_label.grid(column=1, row=11) self.c3_label.grid(column=1, row=12) self.c4_label.grid(column=1, row=13) self.c1_label.bind("<Button-1>", lambda _: self.pick_color("color1", self.c1_label)) self.c2_label.bind("<Button-1>", lambda _: self.pick_color("color2", self.c2_label)) self.c3_label.bind("<Button-1>", lambda _: self.pick_color("color3", self.c3_label)) self.c4_label.bind("<Button-1>", lambda _: self.pick_color("color4", self.c4_label)) ### Function Buttons ### self.buttons = tk.Frame(self) self.buttons.grid(row=1, column=1) tk.Button(self.buttons, text="render", command=self.render_image).grid(column=0, row=0) tk.Button(self.buttons, text="save", command=self.save_to_file).grid(column=1, row=0) tk.Button(self.buttons, text="load", command=self.load_from_file).grid(column=2, row=0) save_im_button = tk.Button(self.buttons, text="save image", command=self.save_image) if not _pil_available: save_im_button['state'] = tk.DISABLED save_im_button.grid(column=3, row=0) self.files = {} ### File List ### self.right = tk.Frame(self) self.right.grid(row=0, column=2, sticky=(tk.N+tk.S)) self.fscroll = tk.Scrollbar(self.right) self.fscroll.grid(row=0, column=1, sticky=(tk.N+tk.S)) self.filebrowser = tk.Listbox(self.right, yscrollcommand=self.fscroll.set, height=20) self.filebrowser.grid(row=0, column=0) self.fscroll.config(command=self.filebrowser.yview) self.filebrowser.bind("<<ListboxSelect>>", self.load_selected_file) self.fill_file_browser() tk.Button(self.right, text="Reset File List", command=self.fill_file_browser).grid(row=1, column=0) ### Canvas ### self.cv = TurtleCanvas(self, width=self.w, height=self.h, bg='white') self.cv.grid(column=1, row=0) ### Status Bar ### tk.Label(self, textvariable=self.status_text).grid(row=2, columnspan=3, sticky=tk.W) self.drawing_thread = None self.turtle_string_creation = None self.grid() # Load command line argument try: self.load_from_file(fname=sys.argv[1]) except IndexError: pass
def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.parent.title("L System Equations Rendering Tool for Tkinter") ### variables ### self.iterations = tk.StringVar() self.angle = tk.StringVar() self.axiom = tk.StringVar() self.rule1 = tk.StringVar() self.rule2 = tk.StringVar() self.rule3 = tk.StringVar() self.rule4 = tk.StringVar() self.constants = tk.StringVar() self.status_text = tk.StringVar() if _pil_available: self.status_text.set("Using PIL for rendering") else: self.status_text.set("Using tk Canvas for rendering") self.color1 = "#000000" self.color2 = "#dd0000" self.color3 = "#00dd00" self.color4 = "#0000dd" self.lsf_dir = expanduser(join("~", "lsf-files")) if not isdir(self.lsf_dir): makedirs(self.lsf_dir) self.example_dir = join(dirname(__file__), "examples") self.entries = tk.Frame(self) self.entries.grid(row=0, column=0, sticky=tk.N) ### Labels ### tk.Label(self.entries, text="Settings", font="Helvetica 14 bold").grid(column=0, row=0, sticky=tk.W) tk.Label(self.entries, text="Iterations").grid(column=0, row=1, padx=5, pady=5) tk.Label(self.entries, text="angle").grid(column=0, row=2, padx=5, pady=5) tk.Label(self.entries, text="axiom").grid(column=0, row=3, padx=5, pady=5) tk.Label(self.entries, text="rule1").grid(column=0, row=4, padx=5, pady=5) tk.Label(self.entries, text="rule2").grid(column=0, row=5, padx=5, pady=5) tk.Label(self.entries, text="rule3").grid(column=0, row=6, padx=5, pady=5) tk.Label(self.entries, text="rule4").grid(column=0, row=7, padx=5, pady=5) tk.Label(self.entries, text="constants").grid(column=0, row=8, padx=5, pady=5) tk.Label(self.entries, text="Color Values", font="Helvetica 14 bold").grid(column=0, row=9, padx=5, pady=5) tk.Label(self.entries, text="default (color 1):").grid(column=0, row=10, padx=5, pady=5) tk.Label(self.entries, text="color 2:").grid(column=0, row=11, padx=5, pady=5) tk.Label(self.entries, text="color 3:").grid(column=0, row=12, padx=5, pady=5) tk.Label(self.entries, text="color 4:").grid(column=0, row=13, padx=5, pady=5) ### Entries ### tk.Entry(self.entries, textvariable=self.iterations).grid(column=1, row=1) tk.Entry(self.entries, textvariable=self.angle).grid(column=1, row=2) tk.Entry(self.entries, textvariable=self.axiom).grid(column=1, row=3) tk.Entry(self.entries, textvariable=self.rule1).grid(column=1, row=4) tk.Entry(self.entries, textvariable=self.rule2).grid(column=1, row=5) tk.Entry(self.entries, textvariable=self.rule3).grid(column=1, row=6) tk.Entry(self.entries, textvariable=self.rule4).grid(column=1, row=7) tk.Entry(self.entries, textvariable=self.constants).grid(column=1, row=8) ## Color settings self.c1_label = tk.Label(self.entries, text=self.color1, bg=self.color1) self.c2_label = tk.Label(self.entries, text=self.color2, bg=self.color2) self.c3_label = tk.Label(self.entries, text=self.color3, bg=self.color3) self.c4_label = tk.Label(self.entries, text=self.color4, bg=self.color4) self.c1_label.grid(column=1, row=10) self.c2_label.grid(column=1, row=11) self.c3_label.grid(column=1, row=12) self.c4_label.grid(column=1, row=13) self.c1_label.bind("<Button-1>", lambda _: self.pick_color("color1", self.c1_label)) self.c2_label.bind("<Button-1>", lambda _: self.pick_color("color2", self.c2_label)) self.c3_label.bind("<Button-1>", lambda _: self.pick_color("color3", self.c3_label)) self.c4_label.bind("<Button-1>", lambda _: self.pick_color("color4", self.c4_label)) ### Function Buttons ### self.buttons = tk.Frame(self) self.buttons.grid(row=1, column=1) tk.Button(self.buttons, text="render", command=self.render_image).grid(column=0, row=0) tk.Button(self.buttons, text="save", command=self.save_to_file).grid(column=1, row=0) tk.Button(self.buttons, text="load", command=self.load_from_file).grid(column=2, row=0) save_im_button = tk.Button(self.buttons, text="save image", command=self.save_image) if not _pil_available: save_im_button['state'] = tk.DISABLED save_im_button.grid(column=3, row=0) self.files = {} ### File List ### self.right = tk.Frame(self) self.right.grid(row=0, column=2, sticky=(tk.N + tk.S)) self.fscroll = tk.Scrollbar(self.right) self.fscroll.grid(row=0, column=1, sticky=(tk.N + tk.S)) self.filebrowser = tk.Listbox(self.right, yscrollcommand=self.fscroll.set, height=20) self.filebrowser.grid(row=0, column=0) self.fscroll.config(command=self.filebrowser.yview) self.filebrowser.bind("<<ListboxSelect>>", self.load_selected_file) self.fill_file_browser() tk.Button(self.right, text="Reset File List", command=self.fill_file_browser).grid(row=1, column=0) ### Canvas ### self.cv = TurtleCanvas(self, width=self.w, height=self.h, bg='white') self.cv.grid(column=1, row=0) ### Status Bar ### tk.Label(self, textvariable=self.status_text).grid(row=2, columnspan=3, sticky=tk.W) self.drawing_thread = None self.turtle_string_creation = None self.grid() # Load command line argument try: self.load_from_file(fname=sys.argv[1]) except IndexError: pass
class Main(tk.Frame): w = 600 h = 600 def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.parent.title("L System Equations Rendering Tool for Tkinter") ### variables ### self.iterations = tk.StringVar() self.angle = tk.StringVar() self.axiom = tk.StringVar() self.rule1 = tk.StringVar() self.rule2 = tk.StringVar() self.rule3 = tk.StringVar() self.rule4 = tk.StringVar() self.constants = tk.StringVar() self.status_text = tk.StringVar() if _pil_available: self.status_text.set("Using PIL for rendering") else: self.status_text.set("Using tk Canvas for rendering") self.color1 = "#000000" self.color2 = "#dd0000" self.color3 = "#00dd00" self.color4 = "#0000dd" self.lsf_dir = expanduser(join("~", "lsf-files")) if not isdir(self.lsf_dir): makedirs(self.lsf_dir) self.example_dir = join(dirname(__file__), "examples") self.entries = tk.Frame(self) self.entries.grid(row=0, column=0, sticky=tk.N) ### Labels ### tk.Label(self.entries, text="Settings", font="Helvetica 14 bold").grid(column=0, row=0, sticky=tk.W) tk.Label(self.entries, text="Iterations").grid(column=0, row=1, padx=5, pady=5) tk.Label(self.entries, text="angle").grid(column=0, row=2, padx=5, pady=5) tk.Label(self.entries, text="axiom").grid(column=0, row=3, padx=5, pady=5) tk.Label(self.entries, text="rule1").grid(column=0, row=4, padx=5, pady=5) tk.Label(self.entries, text="rule2").grid(column=0, row=5, padx=5, pady=5) tk.Label(self.entries, text="rule3").grid(column=0, row=6, padx=5, pady=5) tk.Label(self.entries, text="rule4").grid(column=0, row=7, padx=5, pady=5) tk.Label(self.entries, text="constants").grid(column=0, row=8, padx=5, pady=5) tk.Label(self.entries, text="Color Values", font="Helvetica 14 bold").grid(column=0, row=9, padx=5, pady=5) tk.Label(self.entries, text="default (color 1):").grid(column=0, row=10, padx=5, pady=5) tk.Label(self.entries, text="color 2:").grid(column=0, row=11, padx=5, pady=5) tk.Label(self.entries, text="color 3:").grid(column=0, row=12, padx=5, pady=5) tk.Label(self.entries, text="color 4:").grid(column=0, row=13, padx=5, pady=5) ### Entries ### tk.Entry(self.entries, textvariable=self.iterations).grid(column=1, row=1) tk.Entry(self.entries, textvariable=self.angle).grid(column=1, row=2) tk.Entry(self.entries, textvariable=self.axiom).grid(column=1, row=3) tk.Entry(self.entries, textvariable=self.rule1).grid(column=1, row=4) tk.Entry(self.entries, textvariable=self.rule2).grid(column=1, row=5) tk.Entry(self.entries, textvariable=self.rule3).grid(column=1, row=6) tk.Entry(self.entries, textvariable=self.rule4).grid(column=1, row=7) tk.Entry(self.entries, textvariable=self.constants).grid(column=1, row=8) ## Color settings self.c1_label = tk.Label(self.entries, text=self.color1, bg=self.color1) self.c2_label = tk.Label(self.entries, text=self.color2, bg=self.color2) self.c3_label = tk.Label(self.entries, text=self.color3, bg=self.color3) self.c4_label = tk.Label(self.entries, text=self.color4, bg=self.color4) self.c1_label.grid(column=1, row=10) self.c2_label.grid(column=1, row=11) self.c3_label.grid(column=1, row=12) self.c4_label.grid(column=1, row=13) self.c1_label.bind("<Button-1>", lambda _: self.pick_color("color1", self.c1_label)) self.c2_label.bind("<Button-1>", lambda _: self.pick_color("color2", self.c2_label)) self.c3_label.bind("<Button-1>", lambda _: self.pick_color("color3", self.c3_label)) self.c4_label.bind("<Button-1>", lambda _: self.pick_color("color4", self.c4_label)) ### Function Buttons ### self.buttons = tk.Frame(self) self.buttons.grid(row=1, column=1) tk.Button(self.buttons, text="render", command=self.render_image).grid(column=0, row=0) tk.Button(self.buttons, text="save", command=self.save_to_file).grid(column=1, row=0) tk.Button(self.buttons, text="load", command=self.load_from_file).grid(column=2, row=0) save_im_button = tk.Button(self.buttons, text="save image", command=self.save_image) if not _pil_available: save_im_button['state'] = tk.DISABLED save_im_button.grid(column=3, row=0) self.files = {} ### File List ### self.right = tk.Frame(self) self.right.grid(row=0, column=2, sticky=(tk.N+tk.S)) self.fscroll = tk.Scrollbar(self.right) self.fscroll.grid(row=0, column=1, sticky=(tk.N+tk.S)) self.filebrowser = tk.Listbox(self.right, yscrollcommand=self.fscroll.set, height=20) self.filebrowser.grid(row=0, column=0) self.fscroll.config(command=self.filebrowser.yview) self.filebrowser.bind("<<ListboxSelect>>", self.load_selected_file) self.fill_file_browser() tk.Button(self.right, text="Reset File List", command=self.fill_file_browser).grid(row=1, column=0) ### Canvas ### self.cv = TurtleCanvas(self, width=self.w, height=self.h, bg='white') self.cv.grid(column=1, row=0) ### Status Bar ### tk.Label(self, textvariable=self.status_text).grid(row=2, columnspan=3, sticky=tk.W) self.drawing_thread = None self.turtle_string_creation = None self.grid() # Load command line argument try: self.load_from_file(fname=sys.argv[1]) except IndexError: pass def load_selected_file(self, _): sel = self.filebrowser.curselection() fpath = self.files[self.filebrowser.get(sel[0])] self.load_from_file(fpath) def fill_file_browser(self): root_dirs = (self.lsf_dir, self.example_dir) self.files = {} self.filebrowser.delete(0, tk.END) for directory in root_dirs: for f in glob(join(directory, "*.lsf")): fname = basename(f) self.files[fname] = f self.filebrowser.insert(0, fname) def pick_color(self, colorname, label): old_color = getattr(self, colorname) # discard (r,g,b) and use #rrggbb instead _, new_color = colorchooser.askcolor(initialcolor=old_color, title="Pick a color") setattr(self, colorname, new_color) label['text'] = new_color label['bg'] = new_color def save_to_file(self): fn = filedialog.asksaveasfilename(initialdir=self.lsf_dir, filetypes=(('L-System Formula File', '*.lsf'), ('All files', '*.*'))) if not fn: return if not fn.endswith(".lsf"): fn += ".lsf" try: with open(fn, "w") as f: f.write("\n".join((self.iterations.get(), self.angle.get(), self.axiom.get(), self.rule1.get(), self.rule2.get(), self.rule3.get(), self.rule4.get(), self.constants.get(), "EOF"))) except Exception as e: messagebox.showerror("Couldn't save", e) def load_from_file(self, fname=None): if not fname: fname = filedialog.askopenfilename(initialdir=self.lsf_dir, filetypes=(("L-System Formula", "*.lsf"), ("all files", "*.*"))) if not fname: # User can click cancel return with open(fname, "r") as f: x = f.readlines() self.iterations.set(x[0].strip()) self.angle.set(x[1].strip()) self.axiom.set(x[2].strip()) self.rule1.set(x[3].strip()) self.rule2.set(x[4].strip()) self.rule3.set(x[5].strip()) self.rule4.set(x[6].strip()) self.constants.set(x[7].strip()) self.render_image() def save_image(self): with filedialog.asksaveasfile(filetypes=(('Jpeg Image', '*.jpg;*.jpeg;*.JPEG;*.JPG'), ('Bitmap Image', '*.bmp'), ('Png Image', '*.png'))) as f: self.cv.pil_image.save(f) @property def get_rules(self): """ :rtype : dict :return: dictionary of l-system rules """ rules = dict() for r in ("rule1", "rule2", "rule3", "rule4"): text = getattr(self, r).get() if ":" in text: kv = text.split(":") rules[kv[0]] = "".join(kv[1:]) return rules def render_image_continue(self): if self.turtle_string_creation.job_done(): self.status_text.set("Rendering image") angle = int(self.angle.get()) constants = self.constants.get() t = Turtle(self.turtle_string_creation.string, angle, placeholders=["1", "2", "3", "4"], null_characters=constants) if self.drawing_thread: self.drawing_thread.stop_drawing() self.drawing_thread.join() self.drawing_thread = DrawTurtle(self.cv, t, colors={"1": self.color1, "2": self.color2, "3": self.color3, "4": self.color4}) self.drawing_thread.daemon = True self.drawing_thread.start() else: self.after(100, self.render_image_continue) def render_image(self): angle = self.angle.get() iterations = self.iterations.get() string = self.axiom.get() rules = self.get_rules try: iterations = int(iterations) except ValueError: messagebox.showerror("Missing Information", "You didn't specify iterations") return try: int(angle) except ValueError: messagebox.showerror("Missing Information", "You didn't specify angle") return if iterations > 15: if not messagebox.askyesno("Iterations too high", "Number of iterations is" "too high. This might cause performance problems." "Are you sure about this?"): return # Produce string if self.turtle_string_creation: self.turtle_string_creation.stop_creating() self.turtle_string_creation.join() self.turtle_string_creation = CreateTurtleString(string, rules, iterations) self.turtle_string_creation.start() self.status_text.set("Creating turtle string") self.after(100, self.render_image_continue) def fill_entries(self, it="", ang="", cons="", axi="", r1="", r2="", r3="", r4=""): self.iterations.set(it) self.angle.set(ang) self.constants.set(cons) self.axiom.set(axi) self.rule1.set(r1) self.rule2.set(r2) self.rule3.set(r3) self.rule4.set(r4) def run(self): self.parent.mainloop()
class Main(tk.Frame): w = 600 h = 600 def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, parent, *args, **kwargs) self.parent = parent self.parent.title("L System Equations Rendering Tool for Tkinter") ### variables ### self.iterations = tk.StringVar() self.angle = tk.StringVar() self.axiom = tk.StringVar() self.rule1 = tk.StringVar() self.rule2 = tk.StringVar() self.rule3 = tk.StringVar() self.rule4 = tk.StringVar() self.constants = tk.StringVar() self.status_text = tk.StringVar() if _pil_available: self.status_text.set("Using PIL for rendering") else: self.status_text.set("Using tk Canvas for rendering") self.color1 = "#000000" self.color2 = "#dd0000" self.color3 = "#00dd00" self.color4 = "#0000dd" self.lsf_dir = expanduser(join("~", "lsf-files")) if not isdir(self.lsf_dir): makedirs(self.lsf_dir) self.example_dir = join(dirname(__file__), "examples") self.entries = tk.Frame(self) self.entries.grid(row=0, column=0, sticky=tk.N) ### Labels ### tk.Label(self.entries, text="Settings", font="Helvetica 14 bold").grid(column=0, row=0, sticky=tk.W) tk.Label(self.entries, text="Iterations").grid(column=0, row=1, padx=5, pady=5) tk.Label(self.entries, text="angle").grid(column=0, row=2, padx=5, pady=5) tk.Label(self.entries, text="axiom").grid(column=0, row=3, padx=5, pady=5) tk.Label(self.entries, text="rule1").grid(column=0, row=4, padx=5, pady=5) tk.Label(self.entries, text="rule2").grid(column=0, row=5, padx=5, pady=5) tk.Label(self.entries, text="rule3").grid(column=0, row=6, padx=5, pady=5) tk.Label(self.entries, text="rule4").grid(column=0, row=7, padx=5, pady=5) tk.Label(self.entries, text="constants").grid(column=0, row=8, padx=5, pady=5) tk.Label(self.entries, text="Color Values", font="Helvetica 14 bold").grid(column=0, row=9, padx=5, pady=5) tk.Label(self.entries, text="default (color 1):").grid(column=0, row=10, padx=5, pady=5) tk.Label(self.entries, text="color 2:").grid(column=0, row=11, padx=5, pady=5) tk.Label(self.entries, text="color 3:").grid(column=0, row=12, padx=5, pady=5) tk.Label(self.entries, text="color 4:").grid(column=0, row=13, padx=5, pady=5) ### Entries ### tk.Entry(self.entries, textvariable=self.iterations).grid(column=1, row=1) tk.Entry(self.entries, textvariable=self.angle).grid(column=1, row=2) tk.Entry(self.entries, textvariable=self.axiom).grid(column=1, row=3) tk.Entry(self.entries, textvariable=self.rule1).grid(column=1, row=4) tk.Entry(self.entries, textvariable=self.rule2).grid(column=1, row=5) tk.Entry(self.entries, textvariable=self.rule3).grid(column=1, row=6) tk.Entry(self.entries, textvariable=self.rule4).grid(column=1, row=7) tk.Entry(self.entries, textvariable=self.constants).grid(column=1, row=8) ## Color settings self.c1_label = tk.Label(self.entries, text=self.color1, bg=self.color1) self.c2_label = tk.Label(self.entries, text=self.color2, bg=self.color2) self.c3_label = tk.Label(self.entries, text=self.color3, bg=self.color3) self.c4_label = tk.Label(self.entries, text=self.color4, bg=self.color4) self.c1_label.grid(column=1, row=10) self.c2_label.grid(column=1, row=11) self.c3_label.grid(column=1, row=12) self.c4_label.grid(column=1, row=13) self.c1_label.bind("<Button-1>", lambda _: self.pick_color("color1", self.c1_label)) self.c2_label.bind("<Button-1>", lambda _: self.pick_color("color2", self.c2_label)) self.c3_label.bind("<Button-1>", lambda _: self.pick_color("color3", self.c3_label)) self.c4_label.bind("<Button-1>", lambda _: self.pick_color("color4", self.c4_label)) ### Function Buttons ### self.buttons = tk.Frame(self) self.buttons.grid(row=1, column=1) tk.Button(self.buttons, text="render", command=self.render_image).grid(column=0, row=0) tk.Button(self.buttons, text="save", command=self.save_to_file).grid(column=1, row=0) tk.Button(self.buttons, text="load", command=self.load_from_file).grid(column=2, row=0) save_im_button = tk.Button(self.buttons, text="save image", command=self.save_image) if not _pil_available: save_im_button['state'] = tk.DISABLED save_im_button.grid(column=3, row=0) self.files = {} ### File List ### self.right = tk.Frame(self) self.right.grid(row=0, column=2, sticky=(tk.N + tk.S)) self.fscroll = tk.Scrollbar(self.right) self.fscroll.grid(row=0, column=1, sticky=(tk.N + tk.S)) self.filebrowser = tk.Listbox(self.right, yscrollcommand=self.fscroll.set, height=20) self.filebrowser.grid(row=0, column=0) self.fscroll.config(command=self.filebrowser.yview) self.filebrowser.bind("<<ListboxSelect>>", self.load_selected_file) self.fill_file_browser() tk.Button(self.right, text="Reset File List", command=self.fill_file_browser).grid(row=1, column=0) ### Canvas ### self.cv = TurtleCanvas(self, width=self.w, height=self.h, bg='white') self.cv.grid(column=1, row=0) ### Status Bar ### tk.Label(self, textvariable=self.status_text).grid(row=2, columnspan=3, sticky=tk.W) self.drawing_thread = None self.turtle_string_creation = None self.grid() # Load command line argument try: self.load_from_file(fname=sys.argv[1]) except IndexError: pass def load_selected_file(self, _): sel = self.filebrowser.curselection() fpath = self.files[self.filebrowser.get(sel[0])] self.load_from_file(fpath) def fill_file_browser(self): root_dirs = (self.lsf_dir, self.example_dir) self.files = {} self.filebrowser.delete(0, tk.END) for directory in root_dirs: for f in glob(join(directory, "*.lsf")): fname = basename(f) self.files[fname] = f self.filebrowser.insert(0, fname) def pick_color(self, colorname, label): old_color = getattr(self, colorname) # discard (r,g,b) and use #rrggbb instead _, new_color = colorchooser.askcolor(initialcolor=old_color, title="Pick a color") setattr(self, colorname, new_color) label['text'] = new_color label['bg'] = new_color def save_to_file(self): fn = filedialog.asksaveasfilename(initialdir=self.lsf_dir, filetypes=(('L-System Formula File', '*.lsf'), ('All files', '*.*'))) if not fn: return if not fn.endswith(".lsf"): fn += ".lsf" try: with open(fn, "w") as f: f.write("\n".join( (self.iterations.get(), self.angle.get(), self.axiom.get(), self.rule1.get(), self.rule2.get(), self.rule3.get(), self.rule4.get(), self.constants.get(), "EOF"))) except Exception as e: messagebox.showerror("Couldn't save", e) def load_from_file(self, fname=None): if not fname: fname = filedialog.askopenfilename(initialdir=self.lsf_dir, filetypes=(("L-System Formula", "*.lsf"), ("all files", "*.*"))) if not fname: # User can click cancel return with open(fname, "r") as f: x = f.readlines() self.iterations.set(x[0].strip()) self.angle.set(x[1].strip()) self.axiom.set(x[2].strip()) self.rule1.set(x[3].strip()) self.rule2.set(x[4].strip()) self.rule3.set(x[5].strip()) self.rule4.set(x[6].strip()) self.constants.set(x[7].strip()) self.render_image() def save_image(self): with filedialog.asksaveasfile(filetypes=(('Jpeg Image', '*.jpg;*.jpeg;*.JPEG;*.JPG'), ('Bitmap Image', '*.bmp'), ('Png Image', '*.png'))) as f: self.cv.pil_image.save(f) @property def get_rules(self): """ :rtype : dict :return: dictionary of l-system rules """ rules = dict() for r in ("rule1", "rule2", "rule3", "rule4"): text = getattr(self, r).get() if ":" in text: kv = text.split(":") rules[kv[0]] = "".join(kv[1:]) return rules def render_image_continue(self): if self.turtle_string_creation.job_done(): self.status_text.set("Rendering image") angle = int(self.angle.get()) constants = self.constants.get() t = Turtle(self.turtle_string_creation.string, angle, placeholders=["1", "2", "3", "4"], null_characters=constants) if self.drawing_thread: self.drawing_thread.stop_drawing() self.drawing_thread.join() self.drawing_thread = DrawTurtle(self.cv, t, colors={ "1": self.color1, "2": self.color2, "3": self.color3, "4": self.color4 }) self.drawing_thread.daemon = True self.drawing_thread.start() else: self.after(100, self.render_image_continue) def render_image(self): angle = self.angle.get() iterations = self.iterations.get() string = self.axiom.get() rules = self.get_rules try: iterations = int(iterations) except ValueError: messagebox.showerror("Missing Information", "You didn't specify iterations") return try: int(angle) except ValueError: messagebox.showerror("Missing Information", "You didn't specify angle") return if iterations > 15: if not messagebox.askyesno( "Iterations too high", "Number of iterations is" "too high. This might cause performance problems." "Are you sure about this?"): return # Produce string if self.turtle_string_creation: self.turtle_string_creation.stop_creating() self.turtle_string_creation.join() self.turtle_string_creation = CreateTurtleString( string, rules, iterations) self.turtle_string_creation.start() self.status_text.set("Creating turtle string") self.after(100, self.render_image_continue) def fill_entries(self, it="", ang="", cons="", axi="", r1="", r2="", r3="", r4=""): self.iterations.set(it) self.angle.set(ang) self.constants.set(cons) self.axiom.set(axi) self.rule1.set(r1) self.rule2.set(r2) self.rule3.set(r3) self.rule4.set(r4) def run(self): self.parent.mainloop()