1

Is there a way to change the size of NavigationToolbar (e.g. the size of zoom button) when embedding matplotlib into Tkinter? I have tried to set the keywords width and height in config, but it did not work. So, any suggestion?

Update
import matplotlib
import os
import Tkinter as tk

from matplotlib.backends.backend_tkagg import NavigationToolbar2TkAgg as NavigationToolbar
from matplotlib.backends.backend_tkagg import ToolTip

class CustomedToolbar(NavigationToolbar):
    def __init__(self, canvas, root):
        NavigationToolbar.__init__(self,canvas,root)

def _Button(self, text, file, command, extension='.ppm'):
    img_file = os.path.join(matplotlib.rcParams['datapath'], 'images', file + extension)
    im = tk.PhotoImage(master=self, file=img_file)
    im = im.zoom(3, 3)
    im = im.subsample(4, 4)
    # Do stuff with im here
    b = tk.Button(master=self, text=text, padx=2, pady=2, image=im, command=command)
    b._ntimage = im
    b.pack(side=tk.LEFT)
    return b

def _init_toolbar(self):
    xmin, xmax = self.canvas.figure.bbox.intervalx
    height, width = 50, xmax-xmin
    tk.Frame.__init__(self, master=self.window,
                                            width=int(width), height=int(height),
                                            borderwidth=2)

    self.update()  # Make axes menu

    for text, tooltip_text, image_file, callback in self.toolitems:
        if text is None:
            # spacer, unhandled in Tk
            pass
        else:
            button = self._Button(text=text, file=image_file, command=getattr(self, callback))
            if tooltip_text is not None:
                ToolTip.createToolTip(button, tooltip_text)

    self.message = tk.StringVar(master=self)
    self._message_label = tk.Label(master=self, textvariable=self.message)
    self._message_label.pack(side=tk.RIGHT)
    self.pack(side=tk.BOTTOM, fill=tk.X)

This is my effort. Thanks fhdrsdg.

Elkan
  • 546
  • 8
  • 23
  • Could you provide a [mcve](http://stackoverflow.com/help/mcve) or an image of the problem you are experiencing together with a clear statement of what you would want to achieve? The way your question is now makes it (at least for me) difficult to understand what your problem exactly is. – fhdrsdg Jan 08 '15 at 11:00
  • @fhdrsdg Thanks for your reply and reminding. The question is refined. – Elkan Jan 08 '15 at 11:41
  • @fhdrsdg I'm sorry I can not add more comments after your answer, so I have to add my comment here. +1 for your anwser as it works. But sadly, only integers are accepted by `im.subsample` or `im.zoom`. And PIL is not standardard library in python. So if I do not use any third-party packages, I found your solution is the only way I can choose. – Elkan Jan 08 '15 at 15:51
  • You could try combinations like `im = im.zoom(2, 2)` `im = im.subsample(3, 3)` to get the images at 2/3 of the size. But that doesn't really improve image quality. – fhdrsdg Jan 08 '15 at 15:58
  • Great idea! May be I have to use another images instead of matplotlib image or process the images using other powerful image processing software. Thanks again. – Elkan Jan 08 '15 at 16:08

1 Answers1

1

If I understand what you want correctly, you can create a custom toolbar class, which inherits from NavigationToolbar2TkAgg. You can the alter the _Button definition in which the buttons are created:

class CustomToolbar(NavigationToolbar2TkAgg):
    def _Button(self, text, file, command, extension='.ppm'):
        img_file = os.path.join(matplotlib.rcParams['datapath'], 'images', file + extension)
        im = Tk.PhotoImage(master=self, file=img_file)
        # Do stuff with im here
        b = Tk.Button(
            master=self, text=text, padx=2, pady=2, image=im, command=command)
        b._ntimage = im
        b.pack(side=Tk.LEFT)
        return b

As you can see, here we have an image file im, which is the image you want to make smaller. Tk.PhotoImage only has subsample() to do this, which lets you shrink the images by a whole factor. For example you could do im = im.subsample(2, 2) to make the images twice as small (or im = im.zoom(2, 2) to make them twice as big).

Maybe someone who is more proficient with PIL could tell you if there's a way to use PIL to make the images any size you want, but I couldn't get that to work.

fhdrsdg
  • 10,297
  • 2
  • 41
  • 62
  • Yes, this is what I want to do and I'll try. One more question is why set keywords `width` and `height` of the attribute `config` does not work? – Elkan Jan 08 '15 at 13:55
  • What object did you call `config` on? – fhdrsdg Jan 08 '15 at 14:01
  • `toolbar = NavigationToolbar2TkAgg(canvas, root)`. The `toolbar` has attribute `config`. – Elkan Jan 08 '15 at 14:33
  • I think `config` configures the frame in which the buttons are, so changing the size of this frame does nothing about the size of the buttons. For me, `width` and `height` do nothing at all, which I suspect has something to do with [this](http://stackoverflow.com/questions/563827/how-do-you-set-a-tkinter-frame-size). – fhdrsdg Jan 08 '15 at 15:00