Matplotlibプロット(Python2.7.3とMatplotlib1.2.0rc2)を表示し、ユーザーがプロットの特定の側面を構成できるようにするTkinterGUIがあります。プロットは大きくなる傾向があるため、図はスクロールするキャンバスに包まれています。プロットを構成する1つの側面は、そのサイズを変更することです。
これで、プロットが適切にスクロールし、サイズ変更も機能する一方で、2つの操作を組み合わせて機能することはできません。以下は、効果を示すためのスクリプトです。(長さについては申し訳ありませんが、これ以上短くすることはできませんでした。)プロットをスクロールして(スクロールバーを使用して)、プロットを小さくしたり大きくしたりすることができます(ボタンを使用)。ただし、スクロールするたびに、図は元のサイズにリセットされます。明らかに、スクロールバーを使用してもフィギュアのサイズが変わらないようにしたいと思います。
import math
from Tkinter import Tk, Button, Frame, Canvas, Scrollbar
import Tkconstants
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
def addScrollingFigure(figure, frame):
# set up a canvas with scrollbars
canvas = Canvas(frame)
canvas.grid(row=0, column=0, sticky=Tkconstants.NSEW)
xScrollbar = Scrollbar(frame, orient=Tkconstants.HORIZONTAL)
yScrollbar = Scrollbar(frame)
xScrollbar.grid(row=1, column=0, sticky=Tkconstants.EW)
yScrollbar.grid(row=0, column=1, sticky=Tkconstants.NS)
canvas.config(xscrollcommand=xScrollbar.set)
xScrollbar.config(command=canvas.xview)
canvas.config(yscrollcommand=yScrollbar.set)
yScrollbar.config(command=canvas.yview)
# plug in the figure
figAgg = FigureCanvasTkAgg(figure, canvas)
mplCanvas = figAgg.get_tk_widget()
mplCanvas.grid(sticky=Tkconstants.NSEW)
# and connect figure with scrolling region
canvas.create_window(0, 0, window=mplCanvas)
canvas.config(scrollregion=canvas.bbox(Tkconstants.ALL))
def changeSize(figure, factor):
oldSize = figure.get_size_inches()
print "old size is", oldSize
figure.set_size_inches([factor * s for s in oldSize])
print "new size is", figure.get_size_inches()
print
figure.canvas.draw()
if __name__ == "__main__":
root = Tk()
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
frame = Frame(root)
frame.grid(column=0, row=0, sticky=Tkconstants.NSEW)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
figure = plt.figure(dpi=150, figsize=(4, 4))
plt.plot(xrange(10), [math.sin(x) for x in xrange(10)])
addScrollingFigure(figure, frame)
buttonFrame = Frame(root)
buttonFrame.grid(row=0, column=1, sticky=Tkconstants.NS)
biggerButton = Button(buttonFrame, text="larger",
command=lambda : changeSize(figure, 1.5))
biggerButton.grid(column=0, row=0)
smallerButton = Button(buttonFrame, text="smaller",
command=lambda : changeSize(figure, .5))
smallerButton.grid(column=0, row=1)
root.mainloop()
プロットとスクロールキャンバスがどのように結び付けられているかについて、私は何かが欠けていると思います。呼び出しのたびにスクロールキャンバス(canvas.create_window(...)
およびを使用)を再構成しようとしましたが、それは役に立ちませんでした。私が仕事に取り掛かった代替案の1つは、サイズを変更するたびに、セットアップ全体(図、キャンバス、スクロールバー)を再生成することでした。(しかし、少し残酷に見えることは別として、古い数字を適切に処分することができず、プログラムが時間の経過とともにかなりのメモリを蓄積するという問題がありました。)canvas.config(...)
changeSize
では、サイズ変更操作後にこれらのスクロールバーを適切に動作させる方法について誰かが考えていますか?