Matplotlib在tkinter中起作用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Matplotlib在tkinter中起作用相关的知识,希望对你有一定的参考价值。
这是我的第一个python项目,所以我明白这个问题可能看起来有点愚蠢。
我正在尝试创建一个Mandelbrot渲染器。我正在从我理解的教程和代码中拼凑代码来制作一些东西。
所以基本上我有渲染器的GUI的所有数学和基本功能,但我无法让matplotlib图实际在tkinter GUI中绘图。
matplolib显示部分实际上是一个需要运行mandelbrot_image(-0.8,-0.7,0,0.1,cmap='hot')
的函数。如果引入了该代码,则绘制Mandelbrot集,但是在不同的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()
答案
这里的主要问题是你创建了两个不同的数字。生活在Tk框架中的那个不是你绘制mandelbrot图像的那个。
因此,您需要在整个代码中使用相同的数字。
一种选择是让mandelbrot_image
创建数字并将其返回以便以后能够将其提供给FigureCanvas
。请参阅下面的完整解决方案。
另一个问题是matplotlib没有figshow
方法。你可能想要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
。
以上是关于Matplotlib在tkinter中起作用的主要内容,如果未能解决你的问题,请参考以下文章
在 tkinter GUI 中更新 matplotlib 图