tkinter Canvas中的Matplotlib:为什么update()和draw()方法之后会起作用?

时间:2017-01-24 15:30:21

标签: python canvas matplotlib tkinter

这是我的第一个tkInter应用程序。我想在tkinter画布上画一个matplotlib图。我阅读了以下链接来构建它:

但结果并不令人满意:在回调方法中没有刷新数字,但只有在我运行应用程序的“重置”按钮时才会刷新。有人能告诉我如何在“PlotCallback”中刷新数字/画布吗?

提前致谢!

#!/usr/bin/env python
# -*- coding: utf8 -*-
import os
import numpy as np
import Tkinter
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure

import tkFileDialog
import tkMessageBox

#=========================
# App Class
#=========================
class Visu(Tkinter.Frame):
    """Main Frame for data visualization
    """

    #------------------------------------
    def __init__(self, parent, **kwargs):
        """Initialisation des widgets
        """
        ### USED VARIABLES (for file and data processing)
        self.dataToPlot = []
        self.itmsToPlot = []
        self.presentsItems = []
        self.chBtnVarLst   = [] # list of "CheckButton" states for items selection
        self.chBtnLst = []      # list of "CheckButton" labels
        self.fic = ""
        self.parent = parent

        ### IHM ###
        Tkinter.Frame.__init__( self, parent, **kwargs )
        self.pack(fill=Tkinter.BOTH)

        # Create Menu Bar
        menuBar = Tkinter.Menu( self )
        menuFic = Tkinter.Menu( menuBar )
        menuFic.add_command(label="Open", command = self.OpenCallback)
        menuFic.add_separator()
        menuFic.add_command(label="Quit", command = self.quit)
        menuHlp = Tkinter.Menu( menuBar )
        menuHlp.add_command(label="Help", command = self.HelpCallback)

        menuBar.add_cascade(label = "File", menu = menuFic)
        menuBar.add_cascade(label = "Help",    menu = menuHlp)
        parent.config(menu = menuBar)

        # Create the Canvas for the plot figure
        self.fig = Figure()
        self.ax  = self.fig.add_subplot(111)
        t = np.arange(0.0, 3.0, 0.01)
        s = np.sin(2*np.pi*t)
        self.ax.plot(t,s)

        self.canvas = FigureCanvasTkAgg(self.fig, master = self)
        self.canvas.show()
        self.canvas.get_tk_widget().pack()

        toolbar = NavigationToolbar2TkAgg(self.canvas, self)
        toolbar.update()
        self.canvas._tkcanvas.pack(side=Tkinter.TOP, expand=1)

        # Create controls
        self.dataFrame = Tkinter.LabelFrame( self, text = "Available data" )
        self.defButton = Tkinter.Checkbutton( self.dataFrame,
                                              text = "Empty",
                                              justify = Tkinter.LEFT,
                                              state =    Tkinter.DISABLED).pack()
        self.dataFrame.pack()

        # Create Buttons
        self.BtnPlot = Tkinter.Button(self, text = "Plot", command = self.PlotCallback, state = Tkinter.DISABLED)
        self.BtnPlot.pack(fill = Tkinter.BOTH, expand=1)
        self.BtnRaZ = Tkinter.Button(self, text = "Reset", command = self.ResetCallback, state = Tkinter.DISABLED)
        self.BtnRaZ.pack(fill = Tkinter.BOTH, expand=1)


    #----------------------
    def OpenCallback(self):
        """Open data file and add selection check buttons
        """
        # Open file
        options = {}
        options['defaultextension'] = '.txt'
        options['initialdir'] = '..'
        options['title'] = 'Choix du fichier'
        options['filetypes'] = [('text files', '.txt'),('all files', '.*')]
        filename = tkFileDialog.askopenfilename(**options)
        self.fic = os.path.basename( filename )

        # Reader file header
        f = open(filename)
        self.presentsItems = f.readline().split()
        f.close()

        # Read data
        self.dataToPlot = np.loadtxt(filename, skiprows=1)



        #--- Frame to select items to be drawn ---
        cnt = 0
        for c in self.presentsItems:
            cbVar = Tkinter.StringVar()
            w = Tkinter.Checkbutton(self.dataFrame,
                                text = c,
                                variable = cbVar,
                                justify = Tkinter.LEFT,
                                onvalue = c)
            w.deselect()
            self.chBtnVarLst.append(cbVar)
            self.chBtnLst.append(w)
            w.grid(row = cnt % 10, column = cnt / 10)
            cnt += 1

        # Buttons activation
        self.BtnPlot['state'] = Tkinter.NORMAL
        self.BtnRaZ['state']  = Tkinter.NORMAL

    #----------------------
    def HelpCallback(self):
        """Instructions on how to use the program
        """
        tkMessageBox.showinfo("Usage", "Work in progress...")

    #----------------------
    def PlotCallback(self):
        # Read chosen items
        for cbVar in self.chBtnVarLst:
            if cbVar.get() != "0":
                self.itmsToPlot.append( cbVar.get() )

        # Plot those items
        self.ax.cla()
        self.fig.suptitle( self.fic )
        for itm in self.itmsToPlot:
            k = self.presentsItems.index(itm)
            self.ax.plot(self.dataToPlot[:,k],label=itm)
        self.ax.set_xlabel("Frame number")
        self.ax.legend()
        self.canvas.get_tk_widget().update()
        self.update()
        self.fig.canvas.draw()

    #-----------------------
    def ResetCallback(self):
        """Forgets the items and data, destroy associated buttons
        """
        for cb in self.chBtnLst:
            cb.destroy()
        self.dataToPlot = []
        self.itmsToPlot = []
        self.presentsItems = []
        self.chBtnLst = []
        self.chBtnVarLst = []
        self.fic = ""

#========
# Main
#========
if __name__=='__main__':
    root = Tkinter.Tk()
    root.wm_title("Visu XDE")
    maVisu = Visu( root )
    maVisu.mainloop()

使用Python 2.7.3,matplotlib 1.1.1rc,Tkinter修订版:81008在Ubuntu 12.04上测试(不幸的是我需要一个仅在12.04中存在的特殊模拟框架)。

1 个答案:

答案 0 :(得分:0)

实际上,问题不在于matplotlib,而是没有正确处理的检查按钮,这不会引发异常或错误,但不要让GUI刷新。创建最小,完整和可验证的例子揭示了它......感谢Sun Bear和Goyo的宝贵帮助。