在 Tkinter 画布中更新时 NagivationToolbar 失败 [英] NagivationToolbar fails when updating in Tkinter canvas

查看:46
本文介绍了在 Tkinter 画布中更新时 NagivationToolbar 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用matplotlib更新Tkinter画布中的两面板图.这是显示我当前理解的最少代码.主要问题是导航工具栏适用于初始图(y = sin(x),y = cos(x)),但是当我按下更新按钮更新它时它失败了.例如,如果我放大曲线,则无法使用主页按钮返回其原始状态.我一直在尝试不同的方法,但都无济于事.我会很感激任何人的建议.我注意到的一个小问题是,如果我想终止情节,我应该转到菜单栏并选择 python/quit Python,否则如果我只是单击情节窗口左上角的 X,终端会冻结(我必须杀死终端).
我正在使用Python 2.7.14和matplotlob 2.1.0.

I am trying to update a two-panel plot in Tkinter canvas using matplotlib. Here is the minimum code that shows my current understanding. The main problem is while the navigation toolbar works for the initial plots (y = sin(x), y = cos(x)), however it fails when I press the update button to update it. For example if I zoom in a curve, I cannot use home button to return to its original state. I have been trying different ways, but to no avail. I would appreciate anyone's suggestions. One minor issue I notice is that if I want to kill the plot, I should go to menubar and select python/quit Python, otherwise if I just click the X at the top left of the plot window, the terminal freezes (I have to kill the terminal).
I am using Python 2.7.14 and matplotlob 2.1.0.

from Tkinter import *
import Tkinter as tk
import ttk
from math import exp
import os  # for loading files or exporting files
import tkFileDialog
##loading matplotlib modules
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec
import numpy as np

top = tk.Tk()
top.title("Intermolecular PDFs")

top_frame = ttk.Frame(top, padding = (10, 10))
top_frame.pack()
fig = plt.figure(figsize=(10, 6), dpi=100) ##create a figure; modify the size here

x = np.linspace(0,1)
y = np.sin(x)
z = np.cos(x)

fig.add_subplot(211)

plt.title("Individual PDFs")
plt.xlabel(ur"r (\u00c5)", labelpad = 3, fontsize = 15)
plt.ylabel(ur"PDF, G (\u00c5$^{-2})$", labelpad = 10, fontsize = 15)
plt.plot(x,y, "r-", lw=2)
plt.xticks(fontsize = 11)
plt.yticks(fontsize = 11)

fig.add_subplot(212)


plt.title("Difference PDFs")
plt.xlabel(ur"r (\u00c5)", labelpad = 3, fontsize = 15)
plt.ylabel(ur"PDF, G (\u00c5$^{-2})$", labelpad = 10, fontsize = 15)
plt.plot(x,z,"g-", lw=2)
plt.xticks(fontsize = 11)
plt.yticks(fontsize = 11)

fig.tight_layout()

canvas = FigureCanvasTkAgg(fig, master = top_frame)
canvas.show()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
#self.canvas.draw()

toolbar = NavigationToolbar2TkAgg(canvas, top_frame)
#self.toolbar.pack()
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)


def update():
    fig.clf()

    new_x = np.linspace(1,100)
    new_y = new_x**2
    new_z = new_x**3
    fig.add_subplot(211)

    plt.title("Individual PDFs")
    plt.xlabel(ur"r (\u00c5)", labelpad = 3, fontsize = 15)
    plt.ylabel(ur"PDF, G (\u00c5$^{-2})$", labelpad = 10, fontsize = 15)
    plt.plot(new_x,new_y, "r-", lw=2)
    plt.xticks(fontsize = 11)
    plt.yticks(fontsize = 11)

    fig.add_subplot(212)


    plt.title("Difference PDFs")
    plt.xlabel(ur"r (\u00c5)", labelpad = 3, fontsize = 15)
    plt.ylabel(ur"PDF, G (\u00c5$^{-2})$", labelpad = 10, fontsize = 15)
    plt.plot(new_x,new_z,"g-", lw=2)
    plt.xticks(fontsize = 11)
    plt.yticks(fontsize = 11)

    fig.tight_layout()
    canvas.show()

ttk.Button(top_frame, text = "update",command = update).pack()


top.mainloop()

推荐答案

主要问题是home键不知道按下时应该指向哪个状态.它所指的原始状态甚至不再存在,因为在此期间该数字已被清除.解决方案是调用

The main problem is that the home button does not know which state it should refer to when being pressed. The original state it would refer to does not even exist any more, because the figure had been cleared in the meantime. The solution to this is to call

toolbar.update()

除其他事项外,将为按钮创建一个新的原始状态,以便在按下按钮时还原为该状态.

which will, amongst other things, create a new home state for the button to revert to when being pressed.

代码还有其他一些小问题:

There are some other minor issues with the code:

  • 除了清除图形之外,您还可以更新其中绘制的线条的数据.这样可以消除很多冗余代码.
  • 我强烈建议在 Tk 中嵌入图形时根本不要使用 pyplot.相反,使用面向对象的方法,创建像图形和轴这样的对象,然后调用它们各自的方法.(我不确定这是否是冻结的原因,因为即使是初始代码在运行时也没有冻结.)
  • 代码中浮动了一些不必要的命令.

以下是一个干净的版本,上面的所有内容都得到了照顾:

The following is a clean version with all the above being taken care of:

import Tkinter as tk
import ttk
##loading matplotlib modules
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import numpy as np

top = tk.Tk()
top.title("Intermolecular PDFs")

top_frame = ttk.Frame(top, padding = (10, 10))
top_frame.pack()

matplotlib.rcParams["xtick.labelsize"] = 11
matplotlib.rcParams["ytick.labelsize"] = 11

fig = Figure(figsize=(10, 6), dpi=100) ##create a figure; modify the size here

x = np.linspace(0,1)
y = np.sin(x)
z = np.cos(x)

ax = fig.add_subplot(211)

ax.set_title("Individual PDFs")
ax.set_xlabel(ur"r (\u00c5)", labelpad = 3, fontsize = 15)
ax.set_ylabel(ur"PDF, G (\u00c5$^{-2})$", labelpad = 10, fontsize = 15)
line, = ax.plot(x,y, "r-", lw=2)

ax2 = fig.add_subplot(212)

ax2.set_title("Difference PDFs")
ax2.set_xlabel(ur"r (\u00c5)", labelpad = 3, fontsize = 15)
ax2.set_ylabel(ur"PDF, G (\u00c5$^{-2})$", labelpad = 10, fontsize = 15)
line2, = ax2.plot(x,z,"g-", lw=2)

canvas = FigureCanvasTkAgg(fig, master = top_frame)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

fig.tight_layout()

toolbar = NavigationToolbar2TkAgg(canvas, top_frame)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)


def update():
    new_x = np.linspace(1,100)
    new_y = new_x**2
    new_z = new_x**3

    line.set_data(new_x,new_y)
    line2.set_data(new_x,new_z)

    ax.relim()
    ax.autoscale()
    ax2.relim()
    ax2.autoscale()
    fig.tight_layout()
    canvas.draw_idle()
    toolbar.update()

ttk.Button(top_frame, text = "update",command = update).pack()


top.mainloop()

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

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

这篇关于在 Tkinter 画布中更新时 NagivationToolbar 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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