2017-02-27 52 views
0

这是我的第一个python项目,所以我明白这个问题看起来有点愚蠢。
我想创建一个Mandelbrot渲染器。我从教程和代码中将代码拼凑在一起,这些代码是我理解的。
所以基本上我有所有的数学和渲染器的GUI的基本功能,但我不能得到matplotlib图实际上在tkinter GUI内图形。
matplolib显示部分实际上是一个需要mandelbrot_image(-0.8,-0.7,0,0.1,cmap='hot')才能运行的功能。如果引入了该代码,Mandelbrot集合会被绘制出来,但在不同的matplotlib窗口中。tkinter中的matplotlib函数

这里是我所有的代码,我预先感谢你,再次表示歉意。

#big thanks and credit goes to to Jean Puget from IBM, SentDex from pythonprogramming.net, and stackoverflow 
    #for teaching me how to use python and inspiring much of this following code 


import matplotlib 
matplotlib.use("TkAgg") 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
from matplotlib.figure import Figure 

import tkinter as tk 
from tkinter import ttk 

import numpy as np 
from numba import jit 

from matplotlib import pyplot as plt 
from matplotlib import colors 



#maths and display code derived/inspired from Jean Francois Puget 
#https://www.ibm.com/developerworks/community/blogs/jfp/entry/My_Christmas_Gift?lang=en 
@jit 
def mandelbrot(z,maxiter,horizon,log_horizon): 
    c = z 
    for n in range(maxiter): 
     az = abs(z) 
     if az > horizon: 
      return n - np.log(np.log(az))/np.log(2) + log_horizon 
     z = z*z + c 
    return 0 

@jit 
def mandelbrot_set(xmin,xmax,ymin,ymax,width,height,maxiter): 
    horizon = 2.0 ** 40 
    log_horizon = np.log(np.log(horizon))/np.log(2) 
    r1 = np.linspace(xmin, xmax, width) 
    r2 = np.linspace(ymin, ymax, height) 
    n3 = np.empty((width,height)) 
    for i in range(width): 
     for j in range(height): 
      n3[i,j] = mandelbrot(r1[i] + 1j*r2[j],maxiter,horizon, log_horizon) 
    return (r1,r2,n3) 


#Display setup 
fig = Figure() 
ax = fig.add_subplot(111) 
xmin = -2.0 
xmax = 0.5 
ymin = -1.25 
ymax = 1.25 
cmap='hot' 
# width=20 
# height=20 
# maxiter=1000 
# gamma=0.3 

def mandelbrot_image(xmin,xmax,ymin,ymax,width=10,height=10,\ 
       maxiter=1000,cmap='jet',gamma=0.3): 
    dpi = 80 
    img_width = dpi * width 
    img_height = dpi * height 
    x,y,z = mandelbrot_set(xmin,xmax,ymin,ymax,img_width,img_height,maxiter) 

    fig, ax = plt.subplots(figsize=(width, height),dpi=72) 
    ticks = np.arange(0,img_width,3*dpi) 
    x_ticks = xmin + (xmax-xmin)*ticks/img_width 
    plt.xticks(ticks, x_ticks) 
    y_ticks = ymin + (ymax-ymin)*ticks/img_width 
    plt.yticks(ticks, y_ticks) 
    ax.set_title(cmap) 
    norm = colors.PowerNorm(gamma) 
    ax.figshow(z.T,cmap=cmap,origin='lower',norm=norm) 


LARGE_FONT= ("Verdana", 12) 


class base(tk.Tk): 

    def __init__(self, *args, **kwargs): 

     tk.Tk.__init__(self, *args, **kwargs) 

     tk.Tk.iconbitmap(self, "iconz.ico") 
     tk.Tk.wm_title(self, "Mandelbrot Renderer") 


     container = tk.Frame(self) 
     container.pack(side="top", fill="both", expand = True) 
     container.grid_rowconfigure(0, weight=1) 
     container.grid_columnconfigure(0, weight=1) 

     menubar = tk.Menu(container) 
     filemenu = tk.Menu(menubar, tearoff=0) 

     filemenu.add_separator() 
     filemenu.add_command(label="Exit", command=quit) 
     menubar.add_cascade(label="File", menu=filemenu) 

     self.frames = {} 

     for F in (StartPage, MainPage, Donate): 

      frame = F(container, self) 

      self.frames[F] = frame 

      frame.grid(row=0, column=0, sticky="nsew") 

     self.show_frame(StartPage) 

    def show_frame(self, cont): 

     frame = self.frames[cont] 
     frame.tkraise() 


class StartPage(tk.Frame): 

    def __init__(self, parent, controller): 
     tk.Frame.__init__(self,parent) 
     label = tk.Label(self, text="Start Page", font=LARGE_FONT) 
     label.pack(pady=10,padx=10) 

     button = ttk.Button(self, text="Lets Begin", 
         command=lambda: controller.show_frame(MainPage)) 
     button.pack() 




class Donate(tk.Frame): 

    def __init__(self, parent, controller): 
     tk.Frame.__init__(self, parent) 
     label = tk.Label(self, text="Donate", font=LARGE_FONT) 
     label.pack(pady=10,padx=10) 

     button1 = ttk.Button(self, text="Back", 
          command=lambda: controller.show_frame(MainPage)) 
     button1.pack() 






class MainPage(tk.Frame): 

    def __init__(self, parent, controller): 
     tk.Frame.__init__(self, parent) 
     label = tk.Label(self, text="Graph Page!", font=LARGE_FONT) 
     label.pack(pady=10,padx=10) 

     button1 = ttk.Button(self, text="Back to Home", 
          command=lambda: controller.show_frame(StartPage)) 
     button1.pack() 

     button2 = ttk.Button(self, text="Donate", 
          command=lambda: controller.show_frame(Donate)) 
     button2.pack() 


     canvas = FigureCanvasTkAgg(fig, self) 
     canvas.show() 
     canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) 

     toolbar = NavigationToolbar2TkAgg(canvas, self) 
     toolbar.update() 
     canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True) 




app = base() 
app.geometry ("800x600") 
app.mainloop() 
+0

我道歉的窘况乱码 – Simon

+0

而不是道歉,你可以为自己工作在产生这个问题的[MCVE]代码。在代码中显示'mandelbrot_image()'函数永远不会被调用!在你用其他代码拼凑在一起的代码中提供一个Donate-Button并且在这里提出一个问题是很讽刺的。在回答问题时,我会得到部分捐款吗? – ImportanceOfBeingErnest

+0

我会尽快创建最小,完整和可验证的问题示例,谢谢让我知道这一点。至于捐款的事情,我的意思是,它更多的是一个笑话,而不是我将要实施的一个实际功能,但如果最终做到这一点,而且有人有足够的资金来抛出一些钱和一个半熟的程序,而不是一切手段我会给一部分。 – Simon

回答

1

这里的主要问题是你创建两个不同的数字。生活在Tk框架中的人不是你绘制mandelbrot图像的人。
所以你需要在整个代码中使用相同的数字。
一个选项是让mandelbrot_image创建图形并将其返回给以后能够将其提供给FigureCanvas。 请参阅下面的完整解决方案。

另一个问题是matplotlib没有figshow方法。您可能需要imshow()

import matplotlib 
matplotlib.use("TkAgg") 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
from matplotlib.figure import Figure 

import Tkinter as tk 

import numpy as np 
from numba import jit 

from matplotlib import pyplot as plt 
from matplotlib import colors 

#maths and display code derived/inspired from Jean Francois Puget 
#https://www.ibm.com/developerworks/community/blogs/jfp/entry/My_Christmas_Gift?lang=en 
@jit 
def mandelbrot(z,maxiter,horizon,log_horizon): 
    c = z 
    for n in range(maxiter): 
     az = abs(z) 
     if az > horizon: 
      return n - np.log(np.log(az))/np.log(2) + log_horizon 
     z = z*z + c 
    return 0 

@jit 
def mandelbrot_set(xmin,xmax,ymin,ymax,width,height,maxiter): 
    horizon = 2.0 ** 40 
    log_horizon = np.log(np.log(horizon))/np.log(2) 
    r1 = np.linspace(xmin, xmax, width) 
    r2 = np.linspace(ymin, ymax, height) 
    n3 = np.empty((width,height)) 
    for i in range(width): 
     for j in range(height): 
      n3[i,j] = mandelbrot(r1[i] + 1j*r2[j],maxiter,horizon, log_horizon) 
    return (r1,r2,n3) 


def mandelbrot_image(xmin=-2.,xmax=0.5,ymin=-1.25,ymax=1.25,width=10,height=10,\ 
       maxiter=1000,cmap='jet',gamma=0.3): 

    dpi = 80 
    img_width = dpi * width 
    img_height = dpi * height 
    x,y,z = mandelbrot_set(xmin,xmax,ymin,ymax,img_width,img_height,maxiter) 

    fig = Figure(figsize=(width, height)) 
    ax = fig.add_subplot(111) 

    ticks = np.arange(0,img_width,3*dpi) 
    x_ticks = xmin + (xmax-xmin)*ticks/img_width 
    plt.xticks(ticks, x_ticks) 
    y_ticks = ymin + (ymax-ymin)*ticks/img_width 
    plt.yticks(ticks, y_ticks) 
    ax.set_title(cmap) 
    norm = colors.PowerNorm(gamma) 
    ax.imshow(z.T,cmap=cmap,origin='lower',norm=norm) 
    return fig 

LARGE_FONT= ("Verdana", 12) 

class base(tk.Tk): 

    def __init__(self, *args, **kwargs): 

     tk.Tk.__init__(self, *args, **kwargs) 

     #tk.Tk.iconbitmap(self, "iconz.ico") 
     tk.Tk.wm_title(self, "Mandelbrot Renderer") 


     container = tk.Frame(self) 
     container.pack(side="top", fill="both", expand = True) 
     container.grid_rowconfigure(0, weight=1) 
     container.grid_columnconfigure(0, weight=1) 

     menubar = tk.Menu(container) 
     filemenu = tk.Menu(menubar, tearoff=0) 

     filemenu.add_separator() 
     filemenu.add_command(label="Exit", command=quit) 
     menubar.add_cascade(label="File", menu=filemenu) 

     self.frames = {} 

     for F in (StartPage, MainPage): 

      frame = F(container, self) 

      self.frames[F] = frame 

      frame.grid(row=0, column=0, sticky="nsew") 

     self.show_frame(StartPage) 

    def show_frame(self, cont): 

     frame = self.frames[cont] 
     frame.tkraise() 


class StartPage(tk.Frame): 

    def __init__(self, parent, controller): 
     tk.Frame.__init__(self,parent) 
     label = tk.Label(self, text="Start Page", font=LARGE_FONT) 
     label.pack(pady=10,padx=10) 

     button = tk.Button(self, text="Lets Begin", 
         command=lambda: controller.show_frame(MainPage)) 
     button.pack() 


class MainPage(tk.Frame): 

    def __init__(self, parent, controller): 
     tk.Frame.__init__(self, parent) 
     label = tk.Label(self, text="Graph Page!", font=LARGE_FONT) 
     label.pack(pady=10,padx=10) 

     button1 = tk.Button(self, text="Back to Home", 
          command=lambda: controller.show_frame(StartPage)) 
     button1.pack() 

     # create a figure with the mandelbrot plot inside 
     fig = mandelbrot_image() 
     # attach this figure to the TK canvas 
     canvas = FigureCanvasTkAgg(fig, self) 
     canvas.show() 
     canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True) 

     toolbar = NavigationToolbar2TkAgg(canvas, self) 
     toolbar.update() 
     canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True) 


app = base() 
app.geometry ("800x600") 
app.mainloop()