24

I'm developing a small Tkinter GUI to draw matplotlib-plots. (It contains a few Entries and assembles the plot according to their content.)

I have designed my plotting widget according to http://matplotlib.org/examples/user_interfaces/embedding_in_tk.html, only I use grid instead of pack:

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.get_tk_widget().grid(row=1,column=4,columnspan=3,rowspan=20)

That part works. But embedding the NavigationToolbar in the same fashion does not. Tkinter breaks down without error when I include the lines:

toolbar = NavigationToolbar2TkAgg( canvas, root )
canvas._tkcanvas.grid(row=22,column=4)

I know this is because NavigationToolbar calls pack internally, and pack and grid don't get along. However, I like grid and would hate to have to redesign my whole GUI just to be able to use the NavigationToolbar.

Is there a workaround so I can use NavigationToolbar2TkAgg via grid? (I have found the advice to "subclass and overload" here, but don't know how to do that.)

Any help greatly appreciated!

LBoss
  • 496
  • 6
  • 15
CodingCat
  • 4,999
  • 10
  • 37
  • 59

4 Answers4

18

Can you create an empty frame, then put the NavigationToolbar in that frame? I assume the NavigationToolbar will then pack itself in that frame. You can then use grid on the frame.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • 4
    I have tried that: `toolbar_frame = Frame(root)` `toolbar_frame.grid(row=21,column=4,columnspan=2)` `toolbar = NavigationToolbar2TkAgg( canvas, toolbar_frame )` That does display the Navigation Toolbar, thank you! But it does not seem to be connected to the FigureCanvas? – CodingCat Oct 16 '12 at 13:17
  • 1
    I just tested the trick for my application. The toolbar acts as expected on the canvas. So I think the answer is yes. – Bogey Jammer Oct 30 '14 at 16:00
15

Here is a code example for what was mentioned in Bryan Oakleys answer (add toolbar to frame, place frame on grid):

    fig = Figure(figsize=(5, 5), dpi=100)

    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.get_tk_widget().grid(row=1,column=4,columnspan=3,rowspan=20)
    # here: plot suff to your fig
    canvas.draw()

    ###############    TOOLBAR    ###############
    toolbarFrame = Frame(master=root)
    toolbarFrame.grid(row=22,column=4)
    toolbar = NavigationToolbar2TkAgg(canvas, toolbarFrame)
LBoss
  • 496
  • 6
  • 15
4

I believe what you're looking for is the pack_toolbar=False kwarg
Your toolbar definition should look something like this:

toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)

The following two lines are executed within the NavigationToolbar2TK constructor:

if pack_toolbar:
        self.pack(side=tk.BOTTOM, fill=tk.X)

So setting pack_toolbar to False disables the internal packing, allowing you to use to use grid as per usual.

toolbar.grid()
Harry
  • 193
  • 1
  • 12
1
# the following works for me. I created an empty frame and display it using the grid
# management system, so the frame will be able to use pack management system
canvas = FigureCanvasTkAgg(fig, root)
canvas.draw()
canvas.get_tk_widget().grid(row=2, column=0)
frame = Frame(root)
frame.grid(row=0, column=1)
toobar = NavigationToolbar2Tk(canvas, frame)
canvas.get_tk_widget().grid(row=1, column=0)
crispengari
  • 7,901
  • 7
  • 45
  • 53