実現したいこと
現在tkinter内のmatplotlibのグラフを動的に変化させることをしています。そこで、グラフ内のある領域をズームした後、ズームした状態でグラフの点の色などを変化させたいです。
問題
現在matplotlibで作成したグラフのツールバーのZoom to rectangleのボタンを押すことでズームすることができていますが、ズームした状態でグラフをcanvas.draw()で再描画すると、ズーム前のグラフ全体を描画した状態に戻ってしまいます。本来はズームを維持した状態で、グラフを変化、再描画させたいです。
試してみたこと
試したと言うより、ズーム状態でのグラフ変更の実現のために試そうと思ってできなかったことです。
matplotlib.backend_toolsのbackend_tools.pyのスクリプトでズームに関わるToolZoomというクラスを見つけました。ToolZoom内の関数にはzoom_mode変数やその他_switch_on_zoom_mode()や_mouse_move()などのイベント関数らしきもの、実際のズーム処理と思われる_set_view_from_bbox()関数などがありますが、それらの関数内でprint()で文字を入れてみても、実際のグラフでズーム時にターミナルに表示されません。
同じようにToolZoomクラスの__init__()コンストラクタでもprint()の文字は出力されないようなので、そもそもこのクラスを呼び出していないように思えます。
私は意図しない挙動を起こす心配があるので、backend_toolsの変数などを外部から変更するなどはできればしたくありません。あくまでも現在ズームモードかだけを読み取れれば、グラフのxlim, ylimなどを変更した再描画でズームすることができると思っています。なので、ツールバーのどのボタンが押されたのか、あるいはズームボタンが押されているのかを確認する方法があるのか知りたいです。、
ぜひ、アドバイスをお願いします。
プログラム
Python
1from tkinter.constants import X 2import matplotlib.pyplot as plt 3from matplotlib.collections import PathCollection 4import numpy as np 5import tkinter as tk 6from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk) 7 8 9def windowDestroy(): 10 root.quit() 11 root.destroy() 12 13def click(event): 14 global select_obj_ind 15 artist = event.artist 16 if isinstance(event.artist, PathCollection): 17 mouse_xy = np.array([event.mouseevent.xdata, event.mouseevent.ydata]) 18 data_xy = np.array(artist.get_offsets().data)[event.ind] 19 object_ind = event.ind[np.argmax(np.square(data_xy-mouse_xy).sum(axis=1))] # 最も近いオブジェクトを選択 20 select_obj_ind = object_ind 21 updateCanvas() 22 23def updateCanvas(): 24 ax.cla() 25 ax.set_xlabel("x") 26 ax.set_ylabel("y") 27 edgecolors = ['none'] * N 28 if select_obj_ind != -1: 29 edgecolors[select_obj_ind] = 'yellow' 30 ax.scatter(x, y, edgecolor=edgecolors, picker=True, pickradius=2.5) 31 canvas.draw() 32 33seed = 0 34select_obj_ind = -1 35print(f'initial seed:{seed}') 36np.random.seed(seed=seed) 37N = 100 38x = np.random.randn(N) 39y = np.random.randn(N) 40 41fig = plt.figure() 42ax = fig.add_subplot(111) 43edgecolors = ['none'] * N 44ax.set_xlabel("x") 45ax.set_ylabel("y") 46ax.scatter(x, y, edgecolor=edgecolors, picker=True, pickradius=2.5) 47 48root = tk.Tk() 49root.protocol('WM_DELETE_WINDOW', windowDestroy) 50 51frame = tk.Frame(root) 52frame.pack(side=tk.TOP, anchor=tk.CENTER, expand=True, fill=tk.BOTH) 53 54canvas = FigureCanvasTkAgg(fig, master=frame) 55canvas.draw() 56canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True) 57canvas.mpl_connect('pick_event', click) 58 59toolbar = NavigationToolbar2Tk(canvas, frame) 60toolbar.update() 61 62root.mainloop() 63
追記・修正
問題のプログラムを再現したコードを載せました。
2次元座標上にランダムに配置した点を散布図として表示し、グラフ内の点をクリックすると、その点のエッジカラーが黄色に変化します。

回答1件
あなたの回答
tips
プレビュー