2017-02-27 50 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()