I wrote up a script a while back to let me play around with fractals. The idea was to have direct access to the script that creates the fractal. None of that close, edit, then run hassle; just edit then run.
renderscript.py contains the GUI:
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfile
class View(tk.Frame):
count = 0
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
tk.Button(self, text="open", command=self.open).pack(fill=tk.X)
tk.Button(self, text="save", command=self.save).pack(fill=tk.X)
tk.Button(self, text="run program", command=self.draw).pack(fill=tk.X)
self.txt = tk.Text(self, height=30)
scr = tk.Scrollbar(self)
scr.config(command=self.txt.yview)
self.txt.config(yscrollcommand=scr.set)
scr.pack(side="right", fill="y", expand=False)
self.txt.pack(side="left", fill="both", expand=True)
self.pack()
def draw(self, size=500):
exec(str(self.txt.get(1.0, tk.END)))
self.pixels = [[(0, 0, 0) for y in range(size)] for x in range(size)]
self.pixels = render(self.pixels)
window = tk.Toplevel(self)
window.resizable(0,0)
canvas = tk.Canvas(window, width=size, height=size, bg='white')
canvas.pack()
img = tk.PhotoImage(width=size, height=size)
canvas.create_image((size/2, size/2), image=img, state="normal")
for y in range(size):
for x in range(size):
img.put(self.rgbtohex(self.pixels[x][y]), (x,y))
window.mainloop()
def rgbtohex(self, rgb):
return ("#" + "{:02X}" * 3).format(*rgb)
def open(self):
self.txt.delete(1.0, tk.END)
self.txt.insert(tk.END, open(askopenfilename()).read())
def save(self):
f = asksaveasfile(mode='w', defaultextension=".py")
if f is None:
return
text2save = str(self.txt.get(1.0, tk.END))
f.write(text2save)
f.close()
if __name__ == "__main__":
root = tk.Tk()
root.resizable(0,0)
main = View(root)
root.mainloop()
fractal.py contains example fractal routines:
class Fractal:
def mandelbrot(self, x, y, scale, center=(2.2, 1.5)):
n = lambda c: self.iterate_mandelbrot(c)
return self.calcolor(x, y, scale, center, n)
def julia(self, x, y, scale, center=(1.5, 1.5)):
n = lambda c: self.iterate_mandelbrot(complex(0.3, 0.6), c)
return self.calcolor(x, y, scale, center, n)
def calcolor(self, x, y, scale, center, nf):
c = complex(x * scale - center[0], y * scale - center[1])
n = nf(c)
if n is None:
v = 1
else:
v = n/100.0
return v
def iterate_mandelbrot(self, c, z = 0):
for n in range(256):
z = z*z +c
if abs(z) > 2.0:
return n
return None
def griderator(self, w, h):
for x in range(w):
for y in range(h):
yield x, y
def render(self, pixels):
scale = 1.0/(len(pixels[0])/3)
for x, y in self.griderator(len(pixels), len(pixels[0])):
i = self.mandelbrot(x, y, scale) * 256
r, g, b = int(i % 16 * 16), int(i % 8 * 32), int(i % 4 * 63)
pixels[x][y] = (r, g, b)
return pixels
global render
render = Fractal().render
The script does block while rendering the script. Try replacing mandelbrot
with julia
. I am looking for feedback on style and usability.