无关的 Matplotlib 图(在 tkinter 中绘图) [英] Extraneous Matplotlib Figure (plot in tkinter)

查看:57
本文介绍了无关的 Matplotlib 图(在 tkinter 中绘图)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

This is my first python project and I am trying to plot the Mandelbrot set in Matplotlib and place it into a tkinter frame. This has already been accomplished however a extraneous empty figure appears along with the GUI. This empty plot has the correct amount of tick marks while the plot in the GUI has the incorrect amount of tick marks on the plot (I cant figure out where the tick values are coming from either, but I suspect pixels). I have also searched for quite some time now on how to solve this problem to no avail. I have tried canvas.draw, messing with the methods and classes and I still cannot figure it out... The following is an excerpt of the code that will run. code specifying the display are in the method named mandelbrot_image and the MainPage class Thank you in advance.

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

推荐答案

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

So apparently a new figure is created because of a call to pyplot.xticks(). While this behaviour is not reproducible in python 2.7 and I'm uncertain about the reasons for it, a solution is to use the API commands of the axes:

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

In order to prevent further complications, it may be sensible to use the matplotlib API througout the code, getting rid of pyplot (plt) entirely.

关于导航栏,我可以在 MainPage __ init __ 函数中使用以下代码来获取它:

Concering the Navigationbar, I was able to obtain it using the following inside the MainPage's __init__ function:

    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.

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

这篇关于无关的 Matplotlib 图(在 tkinter 中绘图)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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