adding scrollbars to plot embedded in tk

I have a plot canvas added to a tk interface (python 2.7.2, matplotlib 1.0.1) according to the recipe here:

http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_tk.html

When the window containing the plot is resized the plot shrinks, often leading to REALLY ugly, unreadable plots.

I tried adding scrollbars to the canvas returned by get_tk_widget() and they connect as expected (using the yview method). Then, I set a scrollarea config option for the canvas.

Everything seems to be working just like a tkinter canvas, but then when the window is resized, the plot still resizes and the scrollbars never activate. I was hoping the plot wouldn't resize and the scrollbars would activate to allow the user to scroll to see the appropriate part of the plot, while still keeping the plot looking pretty.

Is there a way (besides editing backend_tkagg.py self.resize method) that would allow the scrollbars to work properly?

If my question isn't clear, I can mock up some code, but it may be a bit lengthy, so if anyone can steer me in a better direction that would be great.

Thanks,

-Matt

Matt,

Currently, (if I understand the backends and the event handling correctly), mpl makes the assumption that a window resize event directly means a figure resize event. Maybe these two concepts should be decoupled to allow for interception and handling? I don’t know how much work the mpl backends have to do to handle the various possibilities of when to scale the figures and when to use scrollbars. Certainly would be quite messier than the current assumption.

Unless I am being completely unaware of current ways to implement what you want, I would suggest filing a feature request. In the meantime, editing the tk backend might be your best bet.

Cheers,
Ben Root

···

On Wed, Aug 31, 2011 at 2:55 PM, Matthew Hemke <mghemke@…287…> wrote:

I have a plot canvas added to a tk interface (python 2.7.2, matplotlib 1.0.1) according to the recipe here:

http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_tk.html

When the window containing the plot is resized the plot shrinks, often leading to REALLY ugly, unreadable plots.

I tried adding scrollbars to the canvas returned by get_tk_widget() and they connect as expected (using the yview method). Then, I set a scrollarea config option for the canvas.

Everything seems to be working just like a tkinter canvas, but then when the window is resized, the plot still resizes and the scrollbars never activate. I was hoping the plot wouldn’t resize and the scrollbars would activate to allow the user to scroll to see the appropriate part of the plot, while still keeping the plot looking pretty.

Is there a way (besides editing backend_tkagg.py self.resize method) that would allow the scrollbars to work properly?

If my question isn’t clear, I can mock up some code, but it may be a bit lengthy, so if anyone can steer me in a better direction that would be great.

Thanks,

-Matt

Hi Matt,

a possible workaround seems to be to embed the figure's canvas in a second Tk canvas using canvas.create_window(...). The second (embedding) canvas handles the appropriate resizing & scrolling. I have attached a script below to demonstrate. Unfortunately, scrolling is rather sluggish, but it seems to work - the plot is not resized, and you can scroll around to different areas. Does that help?

Cheers
Hans

I have a plot canvas added to a tk interface (python 2.7.2, matplotlib
1.0.1) according to the recipe here:

http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_tk.html

When the window containing the plot is resized the plot shrinks, often
leading to REALLY ugly, unreadable plots.

I tried adding scrollbars to the canvas returned by get_tk_widget() and
they connect as expected (using the yview method). Then, I set a scrollarea
config option for the canvas.

Everything seems to be working just like a tkinter canvas, but then when
the window is resized, the plot still resizes and the scrollbars never
activate. I was hoping the plot wouldn't resize and the scrollbars would
activate to allow the user to scroll to see the appropriate part of the
plot, while still keeping the plot looking pretty.

Is there a way (besides editing backend_tkagg.py self.resize method) that
would allow the scrollbars to work properly?

If my question isn't clear, I can mock up some code, but it may be a bit
lengthy, so if anyone can steer me in a better direction that would be
great.

Thanks,

-Matt

--- start of script ---

from Tkinter import Tk, Frame, Canvas, Scrollbar
from Tkconstants import NSEW, HORIZONTAL, EW, NS, ALL

from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

def doLargePlot():
     from numpy.random import randn

     matrix = randn(100, 100)
     plt.pcolor(matrix)

def getScrollingCanvas(frame):
     """
         Adds a new canvas with scroll bars to the argument frame
         NB: uses grid layout
         @return: the newly created canvas
     """

     frame.grid(sticky=NSEW)
     frame.rowconfigure(0, weight=1)
     frame.columnconfigure(0, weight=1)

     canvas = Canvas(frame)
     canvas.grid(row=0, column=0, sticky=NSEW)

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

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

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

     return canvas

if __name__ == "__main__":

     root = Tk()
     root.rowconfigure(0, weight=1)
     root.columnconfigure(0, weight=1)

     frame = Frame(root)

     scrollC = getScrollingCanvas(frame)

     # use more dpi for bigger plot
     #figure = plt.figure(dpi=200)
     figure = plt.figure()

     mplCanvas = FigureCanvasTkAgg(figure, scrollC)
     canvas = mplCanvas.get_tk_widget()
     canvas.grid(sticky=NSEW)

     scrollC.create_window(0, 0, window=canvas)
     scrollC.config(scrollregion=scrollC.bbox(ALL))
     doLargePlot()

     root.mainloop()

--- end of script ---

···

On Wed, 31 Aug 2011 22:19:26 +0200, Benjamin Root <ben.root@...1304...> wrote:

On Wed, Aug 31, 2011 at 2:55 PM, Matthew Hemke <mghemke@...287...> wrote: