【问题标题】:Extraneous Matplotlib Figure (plot in tkinter)无关的 Matplotlib 图(tkinter 中的绘图)
【发布时间】:2017-07-19 07:32:27
【问题描述】:

这是我的第一个 python 项目,我正在尝试在 Matplotlib 中绘制 Mandelbrot 集并将其放入 tkinter 框架中。这已经完成,但是与 GUI 一起出现了一个无关的空白图形。这个空图具有正确数量的刻度线,而 GUI 中的绘图具有不正确数量的刻度线(我无法弄清楚刻度值的来源,但我怀疑像素)。我现在也搜索了很长时间关于如何解决这个问题无济于事。我已经尝试过 canvas.draw,弄乱了方法和类,但我仍然无法弄清楚......以下是将运行的代码的摘录。指定显示的代码在名为 mandelbrot_image 的方法和 MainPage 类中 提前谢谢你。

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
from tkinter import *


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)




LARGE_FONT= ("Verdana", 12)

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("The Mandelbrot set")
    norm = colors.PowerNorm(gamma)
    ax.imshow(z.T,cmap=cmap,origin='lower',norm=norm)


    return fig

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)

        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 getcheckvalue(self):
        print (self.mvar.get())

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




        fig = mandelbrot_image()
        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 图中,而不是 GUI 中的图
  • 您还没有提供an answer解决出现两个数字的问题吗?你之间有什么改变?
  • 您提供的答案将绘图插入到 tkinter 画布中(我很感激)。第二个数字伴随着解决方案。
  • 你是说我之前的回答没有解决出现两个数字的问题吗?
  • 不,你确实回答了我之前的问题(这是如何将 matplotlib 图嵌入到 tkinter 画布中 | 谢谢你的帮助)这是一个不同的问题

标签: python matplotlib tkinter


【解决方案1】:

显然,由于对pyplot.xticks() 的调用而创建了一个新图形。虽然这种行为在 python 2.7 中无法重现,而且我不确定其原因,但解决方案是使用 axes 的 API 命令:

ticks = np.arange(0,img_width,3*dpi)
x_ticks = xmin + (xmax-xmin)*ticks/img_width
y_ticks = ymin + (ymax-ymin)*ticks/img_width
ax.set_xticks(ticks)
ax.set_xticklabels(x_ticks)
ax.set_yticks(ticks)
ax.set_yticklabels(y_ticks)
ax.set_title("The Mandelbrot set")

为了防止进一步的复杂化,明智的做法是在代码中使用 matplotlib API,完全摆脱 pyplot (plt)。

关于导航栏,我可以在MainPage__init__ 函数中使用以下内容获得它:

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

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

【讨论】:

    猜你喜欢
    • 2022-08-13
    • 1970-01-01
    • 2021-04-09
    • 2019-05-15
    • 2014-11-08
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多