Rectangle 27 3

You can make use of pyplot.figure()'s figsize paramater to set the figure size.

self.fig = plt.figure(figsize=(5,5))

python - Embedding Matplotlib in Tkinter, display problems - Stack Ove...

python matplotlib tkinter
Rectangle 27 1

The main loop of tk will take care of the animation, you therefore shouldn't use plt.ion() or plt.pause().

The animating function will be called every interval seconds. You cannot use a while True loop inside this function.

There is no reason whatsoever to supply the animating function to the FigureCanvasTkAgg.

Don't use blit=True unless you know what you're doing. With an interval of one second this is anyways not necessary.

Update the line instead of replotting it in every iteration step.

#import serial
from Tkinter import *
from matplotlib import pyplot as plt
import matplotlib.animation as animation
from matplotlib import style
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


root = Tk()
root.geometry('1200x700+200+100')
root.title('This is my root window')
root.state('zoomed')
root.config(background='#fafafa')

xar = []
yar = []

style.use('ggplot')
fig = plt.figure(figsize=(14, 4.5), dpi=100)
ax1 = fig.add_subplot(1, 1, 1)
ax1.set_ylim(0, 100)
line, = ax1.plot(xar, yar, 'r', marker='o')
#ser = serial.Serial('com3', 9600)

def animate(i):
    #ser.reset_input_buffer()
    #data = ser.readline().decode("utf-8")
    #data_array = data.split(',')
    #yvalue = float(data_array[1])
    yar.append(99-i)
    xar.append(i)
    line.set_data(xar, yar)
    ax1.set_xlim(0, i+1)


plotcanvas = FigureCanvasTkAgg(fig, root)
plotcanvas.get_tk_widget().grid(column=1, row=1)
ani = animation.FuncAnimation(fig, animate, interval=1000, blit=False)
plotcanvas.show()

root.mainloop()

Thanks! That works perfect, exactly what I was looking for. Thanks for the other tips, now I have a better understanding how the code works.

python - Embedding Matplotlib live plot data from Arduino in tkinter c...

python canvas matplotlib tkinter arduino
Rectangle 27 1

You're not accessing Tkinter at all using this code, because your function schart2 returns None, which is then assigned to self.f and used for self.canvas = FigureCanvasTkAgg(self.f).

Rather, the window you're getting is from Matplotlib - the plt.plot and plt.show commands pop up a pure matplotlib figure.

To get an embedded figure in Tkinter the way you want, all you have to do is re-do schart2 to return a figure, and don't use pyplot:

def schart2(stock_sym):
    x = [1,2,3,4]
    y = [20,21,20.5, 20.8]
    fig = Figure()
    axes = fig.add_subplot(111)
    axes.plot(x,y)
    return fig

You'll also want to remove the self.canvas.show(), because it causes a Tkinter error about an 'update_idletasks' attribute, but I'm not enough of a Tkinter expert to figure that one out, plus it's a separate question (there are already a few discussions on SO). There is also a namespace issue - take the Tk. off of side=Tk.TOP, fill=Tk.BOTH, because you've done from Tkinter import *.

Hi, Thank you very much for your response. I made all the changes you suggested and it eliminated the problem of the matplotlib graph not closing correctly however it does bring up another error message. Here is the error message I am receiving: Exception in Tkinter callback Traceback (most recent call last): ... AttributeError: 'NoneType' object has no attribute 'update_idletasks'

My biggest issue is that the primary fix was to the graph code and not to the Tkinter code and because the graph code I used in this post was simplified graph code and not my actual graph code I will have to figure out how to make the necessary adjustments to my actual graph code. Thanks again for your help. Sincerely, George

Well, that was what was causing the behavior you described. The other error is something unrelated. Try looking at the various questions on SO on that topic to see if they answer that question.

python - embedding a matplotlib graph in a Tkinter canvas widget class...

python canvas matplotlib embed
Rectangle 27 3

#---------Imports
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import Tkinter as Tk
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
#---------End of imports

fig = plt.Figure()

x = np.arange(0, 2*np.pi, 0.01)        # x-array

def animate(i):
    line.set_ydata(np.sin(x+i/10.0))  # update the data
    return line,

root = Tk.Tk()

label = Tk.Label(root,text="SHM Simulation").grid(column=0, row=0)

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(column=0,row=1)

ax = fig.add_subplot(111)
line, = ax.plot(x, np.sin(x))
ani = animation.FuncAnimation(fig, animate, np.arange(1, 200), interval=25, blit=False)

Tk.mainloop()

python - Embedding a matplotlib animation into a tkinter frame - Stack...

python animation matplotlib tkinter python-embedding
Rectangle 27 2

self.canvas.show()
self.canvas.show() # insert this line
self.canvas.get_tk_widget().update_idletasks()

Wow, that was easy! I've used show() many times at the end of scripts, but I didn't realize it is also an individual canvas method. Thanks!

ars, I will repost another question with a link to this one, but in case you can resond... If i want to animate contours instead if a colorplot, if i just change the plotting command to: self.a.contour(colors[self.t]) the contour plots show, but instead of updating the canvas as a new plot everytime like pcolor did, they overplot on themselves. Do you know how I can clear the previous contour plots, without using an obvious cla() such that i don't see white? thanks

well, if i self.a.cla() just before the self.a.contour() i don't actually see the canvas clear before the next plot, so it works. But, if there is a better way to set the animation than to cla() i would prefer it because i will also have other data on my plot and don't necessarily want to clear it too. Also, i will be using self.a.plot() as well but it seems to be the exact scenario as contour()

AmyS, that sounds fine. The only question is performance and how smooth your animation needs to be. If it looks fine, don't worry about it. Otherwise, you can look into the "blit" operation, e.g. matplotlib.sourceforge.net/examples/animation/

python - color plot animation with play, pause, stop cabability using ...

python tkinter ipython matplotlib
Rectangle 27 3

Right; after the scrollbar discussion in this answer, I ended up going through this:

.. and I think I managed to get a sort of a scaling code that also scales (somewhat) labels and padding, so (approximately) the whole plot fits inside (note, second image uses "medium" scale from imgur):

For very small sizes, labels again start disappearing - but it still holds OK for a range of sizes.

Note that for newer matplotlib (>= 1.1.1), there is a function figure.tight_layout() that does the margins (but not the font size) for cases like this (it is a single subplot) - but if you're using an older matplotlib, you can do figure.subplots_adjust(left=0.2, bottom=0.15, top=0.86) which is what this example does; and has been tested in:

$ python2.7 -c 'import matplotlib; print(matplotlib.__version__)'
0.99.3
$ python3.2 -c 'import matplotlib; print(matplotlib.__version__)'
1.2.0
tight_layout

Since subplots_adjust takes relative parameters (from 0.0 to 1.0), we can in principle just set them once - and hope they hold for our desired scale range. For the rest (scaling of fonts and labelpad) see the code below:

import math
import sys
if sys.version_info[0] < 3:
  from Tkinter import Tk, Button, Frame, Canvas, Scrollbar
  import Tkconstants
else:
  from tkinter import Tk, Button, Frame, Canvas, Scrollbar
  import tkinter.constants as Tkconstants

import matplotlib
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pprint, inspect

frame = None
canvas = None
ax = None

def printBboxes(label=""):
  global canvas, mplCanvas, interior, interior_id, cwid, figure
  print("  "+label,
    "canvas.bbox:", canvas.bbox(Tkconstants.ALL),
    "mplCanvas.bbox:", mplCanvas.bbox(Tkconstants.ALL),
    "subplotpars:", figure.subplotpars.__dict__ )

def addScrollingFigure(figure, frame):
  global canvas, mplCanvas, interior, interior_id, cwid
  # set up a canvas with scrollbars
  canvas = Canvas(frame)
  canvas.grid(row=1, column=1, sticky=Tkconstants.NSEW)

  xScrollbar = Scrollbar(frame, orient=Tkconstants.HORIZONTAL)
  yScrollbar = Scrollbar(frame)

  xScrollbar.grid(row=2, column=1, sticky=Tkconstants.EW)
  yScrollbar.grid(row=1, column=2, sticky=Tkconstants.NS)

  canvas.config(xscrollcommand=xScrollbar.set)
  xScrollbar.config(command=canvas.xview)
  canvas.config(yscrollcommand=yScrollbar.set)
  yScrollbar.config(command=canvas.yview)

  # plug in the figure
  figAgg = FigureCanvasTkAgg(figure, canvas)
  mplCanvas = figAgg.get_tk_widget()

  # and connect figure with scrolling region
  cwid = canvas.create_window(0, 0, window=mplCanvas, anchor=Tkconstants.NW)
  printBboxes("Init")
  changeSize(figure, 1)

def changeSize(figure, factor):
  global canvas, mplCanvas, interior, interior_id, frame, cwid
  oldSize = figure.get_size_inches()
  print("old size is", oldSize)
  figure.set_size_inches([factor * s for s in oldSize])
  wi,hi = [i*figure.dpi for i in figure.get_size_inches()]
  print("new size is", figure.get_size_inches())
  print("new size pixels: ", wi,hi)
  mplCanvas.config(width=wi, height=hi) ; printBboxes("A")
  canvas.itemconfigure(cwid, width=wi, height=hi) ; printBboxes("B")
  canvas.config(scrollregion=canvas.bbox(Tkconstants.ALL),width=200,height=200)
  tz.set_fontsize(tz.get_fontsize()*factor)
  for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
               ax.get_xticklabels() + ax.get_yticklabels()):
    item.set_fontsize(item.get_fontsize()*factor)
  ax.xaxis.labelpad = ax.xaxis.labelpad*factor
  ax.yaxis.labelpad = ax.yaxis.labelpad*factor
  #figure.tight_layout() # matplotlib > 1.1.1
  figure.subplots_adjust(left=0.2, bottom=0.15, top=0.86)
  figure.canvas.draw() ; printBboxes("C")
  print()

if __name__ == "__main__":
  global root, figure
  root = Tk()
  root.rowconfigure(1, weight=1)
  root.columnconfigure(1, weight=1)

  frame = Frame(root)
  frame.grid(column=1, row=1, sticky=Tkconstants.NSEW)
  frame.rowconfigure(1, weight=1)
  frame.columnconfigure(1, weight=1)

  figure = plt.figure(dpi=150, figsize=(4, 4))
  ax = figure.add_subplot(111)
  ax.plot(range(10), [math.sin(x) for x in range(10)])
  #tz = figure.text(0.5,0.975,'The master title',horizontalalignment='center', verticalalignment='top')
  tz = figure.suptitle('The master title')

  ax.set_title('Tk embedding')
  ax.set_xlabel('X axis label')
  ax.set_ylabel('Y label')
  print(tz.get_fontsize()) # 12.0
  print(ax.title.get_fontsize(), ax.xaxis.label.get_fontsize(), ax.yaxis.label.get_fontsize()) # 14.4 12.0 12.0

  addScrollingFigure(figure, frame)

  buttonFrame = Frame(root)
  buttonFrame.grid(row=1, column=2, sticky=Tkconstants.NS)
  biggerButton = Button(buttonFrame, text="larger",
                        command=lambda : changeSize(figure, 1.2))
  biggerButton.grid(column=1, row=1)
  smallerButton = Button(buttonFrame, text="smaller",
                         command=lambda : changeSize(figure, 0.833))
  smallerButton.grid(column=1, row=2)
  qButton = Button(buttonFrame, text="quit",
                         command=lambda :  sys.exit(0))
  qButton.grid(column=1, row=3)

  root.mainloop()

python - How to get a Matplotlib figure to scroll + resize properly in...

python matplotlib tkinter
Rectangle 27 3

Right; after the scrollbar discussion in this answer, I ended up going through this:

.. and I think I managed to get a sort of a scaling code that also scales (somewhat) labels and padding, so (approximately) the whole plot fits inside (note, second image uses "medium" scale from imgur):

For very small sizes, labels again start disappearing - but it still holds OK for a range of sizes.

Note that for newer matplotlib (>= 1.1.1), there is a function figure.tight_layout() that does the margins (but not the font size) for cases like this (it is a single subplot) - but if you're using an older matplotlib, you can do figure.subplots_adjust(left=0.2, bottom=0.15, top=0.86) which is what this example does; and has been tested in:

$ python2.7 -c 'import matplotlib; print(matplotlib.__version__)'
0.99.3
$ python3.2 -c 'import matplotlib; print(matplotlib.__version__)'
1.2.0
tight_layout

Since subplots_adjust takes relative parameters (from 0.0 to 1.0), we can in principle just set them once - and hope they hold for our desired scale range. For the rest (scaling of fonts and labelpad) see the code below:

import math
import sys
if sys.version_info[0] < 3:
  from Tkinter import Tk, Button, Frame, Canvas, Scrollbar
  import Tkconstants
else:
  from tkinter import Tk, Button, Frame, Canvas, Scrollbar
  import tkinter.constants as Tkconstants

import matplotlib
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pprint, inspect

frame = None
canvas = None
ax = None

def printBboxes(label=""):
  global canvas, mplCanvas, interior, interior_id, cwid, figure
  print("  "+label,
    "canvas.bbox:", canvas.bbox(Tkconstants.ALL),
    "mplCanvas.bbox:", mplCanvas.bbox(Tkconstants.ALL),
    "subplotpars:", figure.subplotpars.__dict__ )

def addScrollingFigure(figure, frame):
  global canvas, mplCanvas, interior, interior_id, cwid
  # set up a canvas with scrollbars
  canvas = Canvas(frame)
  canvas.grid(row=1, column=1, sticky=Tkconstants.NSEW)

  xScrollbar = Scrollbar(frame, orient=Tkconstants.HORIZONTAL)
  yScrollbar = Scrollbar(frame)

  xScrollbar.grid(row=2, column=1, sticky=Tkconstants.EW)
  yScrollbar.grid(row=1, column=2, sticky=Tkconstants.NS)

  canvas.config(xscrollcommand=xScrollbar.set)
  xScrollbar.config(command=canvas.xview)
  canvas.config(yscrollcommand=yScrollbar.set)
  yScrollbar.config(command=canvas.yview)

  # plug in the figure
  figAgg = FigureCanvasTkAgg(figure, canvas)
  mplCanvas = figAgg.get_tk_widget()

  # and connect figure with scrolling region
  cwid = canvas.create_window(0, 0, window=mplCanvas, anchor=Tkconstants.NW)
  printBboxes("Init")
  changeSize(figure, 1)

def changeSize(figure, factor):
  global canvas, mplCanvas, interior, interior_id, frame, cwid
  oldSize = figure.get_size_inches()
  print("old size is", oldSize)
  figure.set_size_inches([factor * s for s in oldSize])
  wi,hi = [i*figure.dpi for i in figure.get_size_inches()]
  print("new size is", figure.get_size_inches())
  print("new size pixels: ", wi,hi)
  mplCanvas.config(width=wi, height=hi) ; printBboxes("A")
  canvas.itemconfigure(cwid, width=wi, height=hi) ; printBboxes("B")
  canvas.config(scrollregion=canvas.bbox(Tkconstants.ALL),width=200,height=200)
  tz.set_fontsize(tz.get_fontsize()*factor)
  for item in ([ax.title, ax.xaxis.label, ax.yaxis.label] +
               ax.get_xticklabels() + ax.get_yticklabels()):
    item.set_fontsize(item.get_fontsize()*factor)
  ax.xaxis.labelpad = ax.xaxis.labelpad*factor
  ax.yaxis.labelpad = ax.yaxis.labelpad*factor
  #figure.tight_layout() # matplotlib > 1.1.1
  figure.subplots_adjust(left=0.2, bottom=0.15, top=0.86)
  figure.canvas.draw() ; printBboxes("C")
  print()

if __name__ == "__main__":
  global root, figure
  root = Tk()
  root.rowconfigure(1, weight=1)
  root.columnconfigure(1, weight=1)

  frame = Frame(root)
  frame.grid(column=1, row=1, sticky=Tkconstants.NSEW)
  frame.rowconfigure(1, weight=1)
  frame.columnconfigure(1, weight=1)

  figure = plt.figure(dpi=150, figsize=(4, 4))
  ax = figure.add_subplot(111)
  ax.plot(range(10), [math.sin(x) for x in range(10)])
  #tz = figure.text(0.5,0.975,'The master title',horizontalalignment='center', verticalalignment='top')
  tz = figure.suptitle('The master title')

  ax.set_title('Tk embedding')
  ax.set_xlabel('X axis label')
  ax.set_ylabel('Y label')
  print(tz.get_fontsize()) # 12.0
  print(ax.title.get_fontsize(), ax.xaxis.label.get_fontsize(), ax.yaxis.label.get_fontsize()) # 14.4 12.0 12.0

  addScrollingFigure(figure, frame)

  buttonFrame = Frame(root)
  buttonFrame.grid(row=1, column=2, sticky=Tkconstants.NS)
  biggerButton = Button(buttonFrame, text="larger",
                        command=lambda : changeSize(figure, 1.2))
  biggerButton.grid(column=1, row=1)
  smallerButton = Button(buttonFrame, text="smaller",
                         command=lambda : changeSize(figure, 0.833))
  smallerButton.grid(column=1, row=2)
  qButton = Button(buttonFrame, text="quit",
                         command=lambda :  sys.exit(0))
  qButton.grid(column=1, row=3)

  root.mainloop()

python - How to get a Matplotlib figure to scroll + resize properly in...

python matplotlib tkinter
Rectangle 27 0

You're not accessing Tkinter at all using this code, because your function schart2 returns None, which is then assigned to self.f and used for self.canvas = FigureCanvasTkAgg(self.f).

Rather, the window you're getting is from Matplotlib - the plt.plot and plt.show commands pop up a pure matplotlib figure.

To get an embedded figure in Tkinter the way you want, all you have to do is re-do schart2 to return a figure, and don't use pyplot:

def schart2(stock_sym):
    x = [1,2,3,4]
    y = [20,21,20.5, 20.8]
    fig = Figure()
    axes = fig.add_subplot(111)
    axes.plot(x,y)
    return fig

You'll also want to remove the self.canvas.show(), because it causes a Tkinter error about an 'update_idletasks' attribute, but I'm not enough of a Tkinter expert to figure that one out, plus it's a separate question (there are already a few discussions on SO). There is also a namespace issue - take the Tk. off of side=Tk.TOP, fill=Tk.BOTH, because you've done from Tkinter import *.

Hi, Thank you very much for your response. I made all the changes you suggested and it eliminated the problem of the matplotlib graph not closing correctly however it does bring up another error message. Here is the error message I am receiving: Exception in Tkinter callback Traceback (most recent call last): ... AttributeError: 'NoneType' object has no attribute 'update_idletasks'

My biggest issue is that the primary fix was to the graph code and not to the Tkinter code and because the graph code I used in this post was simplified graph code and not my actual graph code I will have to figure out how to make the necessary adjustments to my actual graph code. Thanks again for your help. Sincerely, George

Well, that was what was causing the behavior you described. The other error is something unrelated. Try looking at the various questions on SO on that topic to see if they answer that question.

python - embedding a matplotlib graph in a Tkinter canvas widget class...

python canvas matplotlib embed
Rectangle 27 0

The problem is definitely not with how you are appending to your numpy array, or truncating it.

The problem here is with your threading model. Integrating calculation loops with a GUI control loop is difficult.

Fundamentally, you need your GUI threading to have control of when your update code is called (spawning a new thread to handle it if necessary) - so that

  • your code does not block the GUI updating,
  • the GUI updating does not block your code executing and
  • you don't spawn loads of threads holding multiple copies of objects (which might be where your memory leak comes from).

In this case, as your main window is controlled by PyQt4, you want to use a QTimer (see a simple example here)

timer
def task(self):
    getCH4()
    getCO2()
    getConnectedDevices()
    self.dc.update_figure()

def timer(self):
    self.t = QtCore.QTimer()
    self.t.timeout.connect(self.task)
    self.t.start(1000)

and this should work. Keeping the reference to the QTimer is essential - hence self.t = QtCore.QTimer() rather than t = QtCore.QTimer(), otherwise the QTimer object will be garbage collected.

This is a summary of a long thread in chat clarifying the issue and working through several possible solutions. In particular - the OP managed to mock up a simpler runnable example here: http://pastebin.com/RXya6Zah

and the fixed version of the full runnable example is here: http://pastebin.com/gv7Cmapr

The relevant code and explanation is above, but the links might help anyone who wants to replicate / solve the issue. Note that they require PyQt4 to be installed

python - Memory leak when embedding and updating a matplotlib graph in...

python python-3.x matplotlib
Rectangle 27 0

plt.show() will open a new dedicated GUI window to host the figure(s) currently present in the matplotlib state machine. If you don't want that, don't use plt.show(). To be on the save side, best don't use pyplot at all as even such innocent commands as plt.xticks() can cause a new window to open.

Also, get rid of from pylab import *. Pylab is a construct which includes several packages like numpy and pyplot in a single namespace. This may be desired for interactive notebook-like applications, but is usually a bad idea for scripts, as it makes debugging very cumbersome. Instead, try to fully stick to matplotlib API commands.

FigureCanvasTkAgg
NavigationToolbar2TkAgg

python - Embedding matplotlib into a tkinter application - Stack Overf...

python matplotlib tkinter
Rectangle 27 0

There are indeed no errors triggered in the code from the question when being run, but it's also not running as expected. Some errors simply don't get triggered, because the respective part of the code is never called. There are several issues:

  • You need to actually add the FigureCanvas to the Frame outside the animation.
  • Always keep a reference to the objects you want to work on. Especially the animation must stay alive. This is best be done by making it a class attribute using self.
  • You need to actually place the frames to the root window. This can be done using pack.
  • Inside the FuncAnimation you must not call the function to animate but simply provide it as argument. Also, you need to provide some number of frames to animate for the animation to start. FuncAnimation(fig, self.animate_graph, frames=12) instead of FuncAnimation(fig, self.animate_graph(someargument))
  • The animating function needs an argument which is the framenumber (or the list entry from a list that is given by the frames argument). You may provide further arguments if needed (in that case refer to the documentation).

I'm sure I forgot to mention some other things as well. But here is a running code.

from tkinter import * 
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import animation
from matplotlib import style
from matplotlib.figure import Figure
style.use('ggplot')

fig = Figure(figsize=(5, 4), dpi=100)
a = fig.add_subplot(111)

class Controller:

    def __init__(self, root):
        self.root = root
        self.create_left_switches()
        self.create_right_graphs()    

    def create_right_graphs(self):
        right_frame = Frame(self.root)
        right_frame.grid(row=2, column=6, sticky=N+E+W+S,
                         padx=2, pady=2)
        right_frame.pack(fill=X, padx=5, pady=5)
        self.canvas = FigureCanvasTkAgg(fig,right_frame ) 
        self.canvas.get_tk_widget().pack(side=RIGHT, fill=BOTH, expand=True)

        self.anim = animation.FuncAnimation(fig, self.animate_graph, frames=12,
                                       interval=500, repeat=True)
        self.canvas.show()

    def create_left_switches(self):
        left_frame = Frame(self.root)
        left_frame.grid(row=2, column=1, columnspan=6, sticky=N+E+W+S,
                        padx=2, pady=2)
        left_frame.pack(fill=X, padx=5, pady=5)
        led_button = Button(left_frame, text='LED') #command=self.on_led_button_clicked)
        led_button.config(height=2, width=30)
        led_button.grid(row=2, column=0, padx=4, pady=8)


    def animate_graph(self, i):
        pullData = open("sample_graph_data.txt","r").read()
        dataList = pullData.split('\n')
        xList = []
        yList = []
        for eachLine in dataList:
            if len(eachLine)>1:
                x, y = eachLine.split(',')
                xList.append(int(x))
                yList.append(int(y)**(1+i/12.))

        a.clear()
        a.plot(xList, yList)

if __name__ == '__main__':
    root = Tk()
    Controller(root)
    root.mainloop()

python - Embedding matplotlib canvas into tkinter GUI - plot is not sh...

python matplotlib tkinter tkinter-canvas
Rectangle 27 0

I somehow managed to solve the problem. I don't know the exact cause of the problem but after i uninstalled my pythonwin , it seems to work fine without giving me anymore error messages. Thanks A.Rodas for your link for pointing out about pythonwin.

Embedding matplotlib in python tkinter (runtime error) - Stack Overflo...

python matplotlib tkinter
Rectangle 27 0

plt.show() will open a new dedicated GUI window to host the figure(s) currently present in the matplotlib state machine. If you don't want that, don't use plt.show(). To be on the save side, best don't use pyplot at all as even such innocent commands as plt.xticks() can cause a new window to open.

Also, get rid of from pylab import *. Pylab is a construct which includes several packages like numpy and pyplot in a single namespace. This may be desired for interactive notebook-like applications, but is usually a bad idea for scripts, as it makes debugging very cumbersome. Instead, try to fully stick to matplotlib API commands.

FigureCanvasTkAgg
NavigationToolbar2TkAgg

python - Embedding matplotlib into a tkinter application - Stack Overf...

python matplotlib tkinter
Rectangle 27 0

I somehow managed to solve the problem. I don't know the exact cause of the problem but after i uninstalled my pythonwin , it seems to work fine without giving me anymore error messages. Thanks A.Rodas for your link for pointing out about pythonwin.

Embedding matplotlib in python tkinter (runtime error) - Stack Overflo...

python matplotlib tkinter
Rectangle 27 0

You can make use of pyplot.figure()'s figsize paramater to set the figure size.

self.fig = plt.figure(figsize=(5,5))

python - Embedding Matplotlib in Tkinter, display problems - Stack Ove...

python matplotlib tkinter
Rectangle 27 0

Here is an example, I added a button that will start animation:

import numpy as np
import matplotlib

matplotlib.use("TKAgg")
import pylab as pl
fig, ax = pl.subplots()
p = 0
x = np.linspace(0, 10, 200)
y = np.sin(x+p)
line, = ax.plot(x, y)
canvas = fig.canvas.get_tk_widget()

from Tkinter import Button

def anim():
    global p
    p += 0.04
    y = np.sin(x+p)
    line.set_data(x, y)
    fig.canvas.draw()
    canvas.after(50, anim)

def go():
    anim()

b = Button(canvas.master, text="go", command=go)
b.pack()
pl.show()

Thanks but this is just the problem I am having. I cannot get it to take the data from the list I generate. No matter what I try it complains. Here are some of the errors:

File "./anim3.py", line 29, in <module> line, = ax.plot(x, y) raise ValueError("x and y must have same first dimension") ValueError: x and y must have same first dimension If you look at my original code you will see I read a file and fill a list with the values and then the plot is using those values as the y co-ordinate. I cannot find the right way to feed it in

It works fine if I don't try to embed it in a root window or frame or anything else for that matter. If you paste the code and save it as a python script and use the other script to generate the initial data file, saving it in the same directory, it will work great.

python - Embedding an animated matplotlib in tk - Stack Overflow

python matplotlib tkinter python-embedding
Rectangle 27 0

There are indeed no errors triggered in the code from the question when being run, but it's also not running as expected. Some errors simply don't get triggered, because the respective part of the code is never called. There are several issues:

  • You need to actually add the FigureCanvas to the Frame outside the animation.
  • Always keep a reference to the objects you want to work on. Especially the animation must stay alive. This is best be done by making it a class attribute using self.
  • You need to actually place the frames to the root window. This can be done using pack.
  • Inside the FuncAnimation you must not call the function to animate but simply provide it as argument. Also, you need to provide some number of frames to animate for the animation to start. FuncAnimation(fig, self.animate_graph, frames=12) instead of FuncAnimation(fig, self.animate_graph(someargument))
  • The animating function needs an argument which is the framenumber (or the list entry from a list that is given by the frames argument). You may provide further arguments if needed (in that case refer to the documentation).

I'm sure I forgot to mention some other things as well. But here is a running code.

from tkinter import * 
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib import animation
from matplotlib import style
from matplotlib.figure import Figure
style.use('ggplot')

fig = Figure(figsize=(5, 4), dpi=100)
a = fig.add_subplot(111)

class Controller:

    def __init__(self, root):
        self.root = root
        self.create_left_switches()
        self.create_right_graphs()    

    def create_right_graphs(self):
        right_frame = Frame(self.root)
        right_frame.grid(row=2, column=6, sticky=N+E+W+S,
                         padx=2, pady=2)
        right_frame.pack(fill=X, padx=5, pady=5)
        self.canvas = FigureCanvasTkAgg(fig,right_frame ) 
        self.canvas.get_tk_widget().pack(side=RIGHT, fill=BOTH, expand=True)

        self.anim = animation.FuncAnimation(fig, self.animate_graph, frames=12,
                                       interval=500, repeat=True)
        self.canvas.show()

    def create_left_switches(self):
        left_frame = Frame(self.root)
        left_frame.grid(row=2, column=1, columnspan=6, sticky=N+E+W+S,
                        padx=2, pady=2)
        left_frame.pack(fill=X, padx=5, pady=5)
        led_button = Button(left_frame, text='LED') #command=self.on_led_button_clicked)
        led_button.config(height=2, width=30)
        led_button.grid(row=2, column=0, padx=4, pady=8)


    def animate_graph(self, i):
        pullData = open("sample_graph_data.txt","r").read()
        dataList = pullData.split('\n')
        xList = []
        yList = []
        for eachLine in dataList:
            if len(eachLine)>1:
                x, y = eachLine.split(',')
                xList.append(int(x))
                yList.append(int(y)**(1+i/12.))

        a.clear()
        a.plot(xList, yList)

if __name__ == '__main__':
    root = Tk()
    Controller(root)
    root.mainloop()

python - Embedding matplotlib canvas into tkinter GUI - plot is not sh...

python matplotlib tkinter tkinter-canvas
Rectangle 27 0

The problem is definitely not with how you are appending to your numpy array, or truncating it.

The problem here is with your threading model. Integrating calculation loops with a GUI control loop is difficult.

Fundamentally, you need your GUI threading to have control of when your update code is called (spawning a new thread to handle it if necessary) - so that

  • your code does not block the GUI updating,
  • the GUI updating does not block your code executing and
  • you don't spawn loads of threads holding multiple copies of objects (which might be where your memory leak comes from).

In this case, as your main window is controlled by PyQt4, you want to use a QTimer (see a simple example here)

timer
def task(self):
    getCH4()
    getCO2()
    getConnectedDevices()
    self.dc.update_figure()

def timer(self):
    self.t = QtCore.QTimer()
    self.t.timeout.connect(self.task)
    self.t.start(1000)

and this should work. Keeping the reference to the QTimer is essential - hence self.t = QtCore.QTimer() rather than t = QtCore.QTimer(), otherwise the QTimer object will be garbage collected.

This is a summary of a long thread in chat clarifying the issue and working through several possible solutions. In particular - the OP managed to mock up a simpler runnable example here: http://pastebin.com/RXya6Zah

and the fixed version of the full runnable example is here: http://pastebin.com/gv7Cmapr

The relevant code and explanation is above, but the links might help anyone who wants to replicate / solve the issue. Note that they require PyQt4 to be installed

python - Memory leak when embedding and updating a matplotlib graph in...

python python-3.x matplotlib
Rectangle 27 0

self.canvas.show()
self.canvas.show() # insert this line
self.canvas.get_tk_widget().update_idletasks()

Wow, that was easy! I've used show() many times at the end of scripts, but I didn't realize it is also an individual canvas method. Thanks!

ars, I will repost another question with a link to this one, but in case you can resond... If i want to animate contours instead if a colorplot, if i just change the plotting command to: self.a.contour(colors[self.t]) the contour plots show, but instead of updating the canvas as a new plot everytime like pcolor did, they overplot on themselves. Do you know how I can clear the previous contour plots, without using an obvious cla() such that i don't see white? thanks

well, if i self.a.cla() just before the self.a.contour() i don't actually see the canvas clear before the next plot, so it works. But, if there is a better way to set the animation than to cla() i would prefer it because i will also have other data on my plot and don't necessarily want to clear it too. Also, i will be using self.a.plot() as well but it seems to be the exact scenario as contour()

AmyS, that sounds fine. The only question is performance and how smooth your animation needs to be. If it looks fine, don't worry about it. Otherwise, you can look into the "blit" operation, e.g. matplotlib.sourceforge.net/examples/animation/

python - color plot animation with play, pause, stop cabability using ...

python tkinter ipython matplotlib
Rectangle 27 0

I believe the recommendation is not to use pyplot. With wxPython I also like to use the sized_controls, which hide some of the sizer stuff, but still give you control if you need it and at the same time they comply with the platform UI guidelines.

With sizers when you add something you need to tell the container to call Layout/Fit to tell it to adjust itself to the new children.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import wx
import wx.lib.sized_controls as sc

import matplotlib as mpl
mpl.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas

import numpy as np


class CanvasPanel(sc.SizedPanel):
    def __init__(self, parent):
        super(CanvasPanel, self).__init__(parent)
        self.figure = mpl.figure.Figure(figsize=(10, 8), dpi=75,
                                        facecolor='white', edgecolor='white')

        self.fake_depthplot()                                                               
        self.canvas = FigureCanvas(self, -1, self.figure)

        # these print statements give me a number like (1600, 1600)
        # however, when I use the wxpython inspector, it shows that the actual display size is MUCH smaller
        print(self.Size)
        print(self.canvas.Size)

    def fake_depthplot(self):
        main_plot = self.figure
        main_plot.add_axes([0, 0, 1, 1])

        x1 = np.linspace(0.0, 5.0)
        x2 = np.linspace(0.0, 2.0)

        y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)
        y2 = np.cos(2 * np.pi * x2)

        plt = main_plot.add_subplot(4, 2, 1)
        plt.plot(x1, y1, 'ko-')
        plt.title.set_text('A tale of 2 subplots')
        plt.set_ylabel('Damped oscillation')

        plt = main_plot.add_subplot(2, 1, 2)
        plt.plot(x2, y2, 'r.-')
        plt.set_xlabel('time (s)')
        plt.set_ylabel('Undamped')


if __name__ == "__main__":
    app = wx.App()
    fr = sc.SizedFrame(None, title='test')
    print(fr.Size)
    pane = fr.GetContentsPane()
    panel = CanvasPanel(pane)
    fr.Fit()
    import sys
    if '-i' in sys.argv:
        import wx.lib.inspection
        wx.lib.inspection.InspectionTool().Show()
    fr.Show()
    app.MainLoop()

python - sizing problems embedding matplotlib figure in wxpython GUI -...

python matplotlib wxpython