Matklotlib在Tkinter中的功能 [英] Matplotlib functions in tkinter

查看:45
本文介绍了Matklotlib在Tkinter中的功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的第一个python项目,所以我知道这个问题似乎有点愚蠢.
我正在尝试创建一个Mandelbrot渲染器.我正在将我理解的教程和代码中的代码拼凑在一起.
因此,基本上,我具有渲染器GUI的所有数学功能和基本功能,但是我无法让matplotlib图形真正在tkinter GUI中绘制图形.
matplolib显示部分实际上是一个需要运行 mandelbrot_image(-0.8,-0.7,0,0.1,cmap ='hot')的函数.如果引入了该代码,则将绘制Mandelbrot集,但在另一个matplotlib窗口中.

This is my first python project so I understand that this problem may seem a bit stupid.
I am trying to create a Mandelbrot renderer. I am piecing code together from tutorials and code that I understand to make something.
So basically I have all the maths and the basic functions of the GUI for the renderer but I can't get the matplotlib graph to actually graph inside the tkinter GUI.
The matplolib display part is actually a function that needs mandelbrot_image(-0.8,-0.7,0,0.1,cmap='hot') to run. If that code is introduced, the Mandelbrot set is plotted, but in a different matplotlib window.

这是我所有的代码,我提前感谢你,我再次道歉.

Here is all my code, I thank you in advance and once again I apologize.

   #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()

推荐答案

此处的主要问题是创建两个不同的图形.存在于 Tk 帧中的那个不是您绘制曼德勃罗图像的那个.
因此,您需要在整个代码中使用相同的图形.
一种选择是让 mandelbrot_image 创建图形并将其返回给以后,以便能够将其提供给 FigureCanvas .完整解决方案见下文.

The main problem here is that you create two different figures. The one that lives in the Tk frame is not the one you plot the mandelbrot image to.
So you need to work with the same figure throughout the code.
One option is to let the mandelbrot_image create the figure and return it to later be able to supply it to the FigureCanvas. See below for a complete solution.

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

An additional problem is that matplotlib does not have a figshow method. You probably want imshow()instead.

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()

注意:在较新版本的 matplotlib 中,您应该使用 NavigationToolbar2Tk 而不是 NavigationToolbar2TkAgg.

Note: In newer versions of matplotlib you should use NavigationToolbar2Tk instead of NavigationToolbar2TkAgg.

这篇关于Matklotlib在Tkinter中的功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆