5

Dear programmming communauty,

I am trying to perform a "interactive plot" based on Tkinter and pylab.plot in order to plot 1D values. The abssissa are a 1D numpy array x and the ordonates values are in a multidimension array Y, eg.

import numpy
x = numpy.arange(0.0,3.0,0.01)
y = numpy.sin(2*numpy.pi*x)
Y = numpy.vstack((y,y/2))

I want to display y or y/2 (the elements of Y matrix) according to x and change between them with 2 buttons left and right (in order to go to more complex cases). Usually I create some functions like the following to plot graphs.

import pylab
def graphic_plot(n):
    fig = pylab.figure(figsize=(8,5))
    pylab.plot(x,Y[n,:],'x',markersize=2)
    pylab.show()

To add two buttons to change the value of nparameter, I have tried this without success :

import Tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class App:
def __init__(self,master):
    # Create a container
    frame = Tkinter.Frame(master)
    frame.pack()
    # Create 2 buttons
    self.button_left = Tkinter.Button(frame,text="<",command=self.decrease)
    self.button_left.pack(side="left")
    self.button_right = Tkinter.Button(frame,text=">",command=self.increase)
    self.button_right.pack(side="left")
    self.canvas = FigureCanvasTkAgg(fig,master=self)
    self.canvas.show()
def decrease(self):
    print "Decrease"
def increase(self):
    print "Increase"
root = Tkinter.Tk()
app = App(root)
root.mainloop()

Can someone help me to understand how to perform such kind of feature ? Many thanks.

4
  • What error are you getting? Could you elaborate on "I have tried this without success"? Commented Apr 3, 2012 at 17:29
  • First, I can't include graph and buttons into a single window. Secondly, I don't know how to change the value of n parameter with the buttons. Thirdly, I don't know how to 'refresh' the graph after cliking on the button. Commented Apr 3, 2012 at 17:35
  • I don't know about some of those, but to get the canvas to show up, you need to pack it. Googling around a bit, It seems like you might want: canvas.get_tk_widget().pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1) -- or however you want to pack it. (I usually use .grid(), so I'm not sure what the sensible options are to pass to .pack()) Commented Apr 3, 2012 at 17:56
  • Discussed further in stackoverflow.com/questions/33222030/… and stackoverflow.com/questions/33262433/… Commented Oct 22, 2015 at 13:42

1 Answer 1

13

To change the y-values of the line, save the object that's returned when you plot it (line, = ax.plot(...)) and then use line.set_ydata(...). To redraw the plot, use canvas.draw().

As a more complete example based on your code:

import Tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

class App:
    def __init__(self, master):
        # Create a container
        frame = Tkinter.Frame(master)
        # Create 2 buttons
        self.button_left = Tkinter.Button(frame,text="< Decrease Slope",
                                        command=self.decrease)
        self.button_left.pack(side="left")
        self.button_right = Tkinter.Button(frame,text="Increase Slope >",
                                        command=self.increase)
        self.button_right.pack(side="left")

        fig = Figure()
        ax = fig.add_subplot(111)
        self.line, = ax.plot(range(10))

        self.canvas = FigureCanvasTkAgg(fig,master=master)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1)
        frame.pack()

    def decrease(self):
        x, y = self.line.get_data()
        self.line.set_ydata(y - 0.2 * x)
        self.canvas.draw()

    def increase(self):
        x, y = self.line.get_data()
        self.line.set_ydata(y + 0.2 * x)
        self.canvas.draw()

root = Tkinter.Tk()
app = App(root)
root.mainloop()
Sign up to request clarification or add additional context in comments.

2 Comments

This is almost what I want. Thank you. Can you explian me this syntax self.line, = (specially the comma) ? And I lost with this the matplotlib tools (like zoom...), is there a way to bring them back ?
Is it possible to have separated windows (one with classic plot in pylab and a second one with only the two buttons) in order to make this thing simpler to customize ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.