Python Tkinter Embed Matplotlib in GUI
Question: I'm trying to embed a plot in my Tkinter GUI coded in Python. I believe the
code below succeeds in simply putting a graph into a canvas, but I don't have
any control of the canvas location within the GUI grid. I want to be able to
have a subsection of my GUI be the plot...not the entirety of it. How can I
position this canvas widget?

    
    
    #!/usr/apps/Python/bin/python
    import matplotlib, sys
    matplotlib.use('TkAgg')
    from numpy import arange, sin, pi
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
    from matplotlib.figure import Figure
    from Tkinter import *
    
    master = Tk()
    master.title("Hello World!")
    #-------------------------------------------------------------------------------
    
    f = Figure(figsize=(5,4), dpi=100)
    a = f.add_subplot(111)
    t = arange(0.0,3.0,0.01)
    s = sin(2*pi*t)
    a.plot(t,s)
    
    
    dataPlot = FigureCanvasTkAgg(f, master=master)
    dataPlot.show()
    dataPlot.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
    #-------------------------------------------------------------------------------
    master.mainloop()
    


Answer: You don't have any other widgets so it's hard to know where you want other
widgets. Here's what I can tell you though: by doing
`dataPlot.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)` you are asking
Tkinter to fill the screen with the plot. This, because you ask it to fill in
all directions (`fill=BOTH`) and expand to fill any extra space (`expand=1`).

However, you can still add other widgets. `pack` works by putting widgets on
one side of a container. Your container, `master`, always has four sides. So,
for example, if you wanted to create a toolbar you would do something like:

    
    
    toolbar = tk.Frame(master)
    button = tk.Button(toolbar, text="Push me")
    button.pack(side="left") # left side of parent, the toolbar frame
    toolbar.pack(side=TOP, fill="x") # top of parent, the master window
    

Notice that if you put this code _after_ the code where you `pack` the plot,
the toolbar shows up on the bottom! That's because `TOP`, `BOTTOM`, etc refer
to space left over by any other widgets that have already been `pack`ed. The
plot takes up the top, the space left over is at the bottom. So when you
specify `TOP` again it means "at the top of the area below whatever is already
at the top".

So, you have some choices. The best choice is to make your widgets in the
order you wish them to appear. If you `pack` the toolbar at the top before you
`pack` the plot, it will be the toolbar that shows up at the very top.
Further, you can place the plot at the bottom rather than the top and that
will solve the problem, too.

By the way, I typically create my widgets in one block, then lay them all out
in a separate block. I find it makes the code easier to maintain.

Another choice which may fit your mental model better is to `grid` _instead
of_ `pack`. With `grid` you can choose the row(s) and column(s) that the
widget occupies. This makes it easy to lay things out in a grid, but at the
expense of having to use a little more code.

For example, to put the toolbar at the top and the plot down below you might
do:

    
    
    toolbar.grid(row=1, column=1, sticky="ew")
    dataPlot.get_tk_widget().grid(row=1, column=1, sticky="nsew")
    master.grid_rowconfigure(0, weight=0)
    master.grid_rowconfigure(1, weight=1)
    master.grid_columnconfigure(0, weight=1)
    

Notice that rows and columns start at zero. Also, "weight" refers to how much
this widget expands relative to other widgets. With two rows of equal weight,
they will expand equally when the window is resized. A weight of zero means no
expansion. A weight of 2 for one row, and 1 for another means that the former
will expand twice as much as the latter.

For more information see [this page on
grid](http://effbot.org/tkinterbook/grid.htm), and [this page on
pack](http://effbot.org/tkinterbook/pack.htm).

