-1

here is my first tkInter application. I'd like to draw a matplotlib figure in a tkinter canvas. I read the following links to build it :

but the result is not really satisfying : the figure is not refreshed in the callback method, but only when I run the "reset" button of my app. Could someone tell me how to get the figure/canvas refreshed in the "PlotCallback" ?

Thanks in advance !

#!/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()

Tested on Ubuntu 12.04 (unfortunately I need a special simulation framework existing only in 12.04) with Python 2.7.3, matplotlib 1.1.1rc, Tkinter Revision: 81008.

Community
  • 1
  • 1
JSn-54
  • 1
  • 2
  • I recently posted the codes to create a [LIVE matplotlib chart in a tkinter window](http://stackoverflow.com/questions/41629891/matplotlib-removing-patches-from-plot/41705020#41705020). Is this what you need? – Sun Bear Jan 24 '17 at 18:54
  • Maybe you could write a [mcve] with less code and that not depends on external files. – Stop harming Monica Jan 24 '17 at 22:59

1 Answers1

0

Actually, the problem was not with matplotlib but with a checkbutton not processed correctly, which don't raise exception nor error, but don't let the GUI be refreshed. Creating the Minimal, Complete and Verifiable example revealed it... Thanks Sun Bear and Goyo for your valuable help.

JSn-54
  • 1
  • 2