"""
matplotlib.pyplot を tkinter 環境で使用するためのユーティリティクラスと関数を提供します。
このモジュールは、matplotlib.pyplot の機能を拡張し、tkinter との統合を容易にするためのラッパーを提供します。
特に、インタラクティブなプロットを tkinter ウィンドウに組み込む際などに有用です。
:doc:`tkplot_pyplot_usage`
"""
import sys
import time
import tklib.tkimport as imp
mpl = imp.import_lib("matplotlib", stop_by_error = False)
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm
imp.messages(stop_by_error = True)
tk = imp.import_lib("tkinter", stop_by_error = False)
tkpli = imp.import_lib("tklib.tkgraphic.tkplot_tkinter", stop_by_error = False)
imp.messages(stop_by_error = False)
from tklib.tkobject import tkObject
from tklib.tkutils import pint, pfloat, index2val
from tklib.tkgraphic.tkplotevent import tkPlotEvent, RangeSelector
from tklib.tkgraphic.tkplot_tkinter import tkPlot_tkinter
[ドキュメント]
def select_plt(plt = None, use_tkinter = False, parent = None, title = "tkPlot_tkinter"):
"""
matplotlib.pyplot オブジェクトまたは tkPlot_tkinter オブジェクトを選択して返します。
use_tkinter フラグに基づいて、通常の matplotlib.pyplot オブジェクトまたは
tkinter と統合された tkPlot_tkinter オブジェクトを初期化し、関連するオブジェクトとともに返します。
:param plt: matplotlib.pyplot のインスタンス。デフォルトは None で、その場合グローバルな pyplot が使用されます。
:param use_tkinter: True の場合、tkPlot_tkinter オブジェクトを返します。False の場合、標準の pyplot オブジェクトを返します。
:param parent: tkPlot_tkinter を使用する場合の親 tkinter ウィジェット。None の場合、新しい tk.Tk() が作成されます。
:param title: tkPlot_tkinter ウィンドウのタイトル。
:returns: タプル (tkplt, root, tkpyplot)。
tkplt: use_tkinter が True の場合は tkPlot_tkinter オブジェクト、False の場合は matplotlib.pyplot オブジェクト。
root: use_tkinter が True の場合は tkinter のルートウィンドウ、False の場合は None。
tkpyplot: tkPlot_pyplot オブジェクト。
"""
tkpyplot = tkPlot_pyplot(plt)
if not use_tkinter:
root = None
tkplt = plt
return tkplt, root, tkpyplot
else:
if parent is None:
parent = tk.Tk()
tkplt = tkPlot_tkinter(plt, parent = parent, title = title)
return tkplt, parent, tkpyplot
[ドキュメント]
class tkPlot_pyplot(tkObject):
"""
matplotlib.pyplot を拡張し、tkinter との連携を強化するクラスです。
matplotlib.pyplot のラッパーとして機能し、tkinter 環境でのプロット操作や
追加のUI要素(スライダーなど)の統合を容易にします。tkObject を継承しています。
"""
def __init__(self, plt = None, **kwargs):
"""
tkPlot_pyplot クラスのコンストラクタです。
matplotlib.pyplot のインスタンスを保持し、スライダーオブジェクトのリストを初期化します。
:param plt: matplotlib.pyplot のインスタンス。デフォルトは None で、その場合グローバルな pyplot が使用されます。
:param kwargs: tkObject のコンストラクタに渡される追加のキーワード引数。
"""
self.plt = plt
self.sliders = []
def __del__(self):
"""
オブジェクトが破棄される際に呼び出されるデストラクタです。
現在は特別なクリーンアップ処理は行いません。
"""
# print("{} destroyed".format(self.name))
pass
def __str__(self):
"""
オブジェクトの文字列表現を返します。
オブジェクトを str() で変換した際に、その種類とメソッド情報を含む文字列を返します。
:returns: str オブジェクトの文字列表現。
"""
return f"plot object extending matplotlib.pyplot ({self.method})"
[ドキュメント]
def get_window_from_plt(self):
"""
現在の matplotlib の図マネージャーからウィンドウオブジェクトを取得します。
matplotlib が管理する現在の図のウィンドウオブジェクト(通常は tkinter の Toplevel または Tk ウィンドウ)を返します。
:returns: object matplotlib ウィンドウオブジェクト。
"""
return self.plt.get_current_fig_manager().window
[ドキュメント]
def create_window(self, fig):
"""
新しいウィンドウを作成します。
現在は実装されておらず、何もしません。
:param fig: matplotlib の Figure オブジェクト。
"""
pass
[ドキュメント]
def pause(self, duration = 0.001, **kwargs):
"""
matplotlib の描画を一時停止し、イベントを処理します。
親クラス tkObject の pause メソッドを呼び出して、指定された期間だけ
matplotlib のイベントループを一時停止し、UIイベントを処理します。
:param duration: float 一時停止する期間(秒)。デフォルトは 0.001 秒です。
:param kwargs: tkObject.pause に渡される追加のキーワード引数。
"""
super().pause(duration, **kwargs)
[ドキュメント]
def show(self, **kwargs):
"""
matplotlib のプロットウィンドウを表示します。
親クラス tkObject の show メソッドを呼び出して、matplotlib のプロットウィンドウを表示し、イベントループを開始します。
:param kwargs: tkObject.show に渡される追加のキーワード引数。
"""
super().show(**kwargs)
[ドキュメント]
def sleep(self, duration):
"""
指定された期間、プログラムの実行を停止します。
time.sleep() を使用して、プログラムの実行を指定された秒数だけ一時停止させます。
:param duration: float 停止する期間(秒)。
"""
time.sleep(duration)
[ドキュメント]
def subplots(self, ny, nx, figsize = None, dpi = 100, tight_layout = True, **kwargs):
"""
複数のサブプロットを持つ図を作成します。
matplotlib.pyplot.subplots() のラッパーで、指定された行数と列数で
サブプロットのグリッドを作成し、図と軸オブジェクトを返します。
タイトなレイアウトがデフォルトで有効になっています。
:param ny: int 行数。
:param nx: int 列数。
:param figsize: tuple 図のサイズ (幅, 高さ) をインチで指定します。
:param dpi: int 図の解像度(ドット/インチ)。
:param tight_layout: bool constrained_layout を使用して、サブプロットとパディングを自動的に調整するかどうか。
:param kwargs: matplotlib.pyplot.subplots に渡される追加のキーワード引数。
"""
fig, axes = self.plt.subplots(ny, nx, figsize = figsize, dpi = dpi, constrained_layout = tight_layout, **kwargs)
def legend(self, ax, line_inf_list = None, draggable = True, **kwargs):
"""
プロットに凡例を追加します。
複数の線の情報に基づいて凡例を作成し、ドラッグ可能に設定します。
このメソッドは、同じ名前の2つ目のメソッドと重複しています。
:param ax: matplotlib.axes.Axes 凡例を追加する軸オブジェクト。
:param line_inf_list: list 凡例に追加する線の情報のリスト。各要素は matplotlib.lines.Line2D オブジェクトのリストです。
:param draggable: bool 凡例をドラッグ可能にするかどうか。デフォルトは True です。
:param kwargs: ax.legend に渡される追加のキーワード引数。
"""
if line_inf_list is not None:
ins = sum(line_inf_list)
labels = [l.get_label() for l in ins]
_legend = ax.legend(ins, labels, **kwargs)
else:
_legend = ax.legend(**kwargs)
_legend.set_draggable(draggable)
[ドキュメント]
def update(self):
"""
プロットを更新します。
現在は実装されておらず、何もしません。
"""
pass
[ドキュメント]
def legend(self, ax, h_list, l_list = None, is_draggable = True, **kwargs):
"""
プロットに凡例を追加します(重複定義)。
h_list と l_list を使用して凡例を作成し、ドラッグ可能に設定します。
このメソッドは、同じ名前の1つ目のメソッドと重複しています。
:param ax: matplotlib.axes.Axes 凡例を追加する軸オブジェクト。
:param h_list: list 凡例に追加するハンドル(線オブジェクトなど)のリスト。各要素はイテラブルであると想定されます。
:param l_list: list 凡例に追加するラベルのリスト。各要素はイテラブルであると想定されます。None の場合、h_list からラベルを抽出します。
:param is_draggable: bool 凡例をドラッグ可能にするかどうか。デフォルトは True です。
:param kwargs: ax.legend に渡される追加のキーワード引数。
"""
if l_list:
_legend = ax.legend(sum(h_list), sum(l_list), **kwargs)
else:
ins_sum = sum(h_list)
_legend.ax.legend(ins_sum, [l.get_label() for l in ins_sum], **kwargs)
_legend.draggable(is_draggable)
[ドキュメント]
def add_slider(self, box, axcolor = 'lightgoldenrodyellow', label = 'A', min = 0.1, max = 10.0, init = 1.0, cmd = None):
"""
matplotlib のプロットにスライダーを追加します。
指定された位置にスライダーウィジェットを作成し、その値を変更したときに実行されるコマンドを設定します。
作成されたスライダーは内部リストに保持されます。
:param box: list [left, bottom, width, height] の形式でスライダーの軸の位置を指定するリスト。単位は図の幅と高さに対する相対的な座標です。
:param axcolor: str スライダーの軸の背景色。
:param label: str スライダーのラベル。
:param min: float スライダーの最小値。
:param max: float スライダーの最大値。
:param init: float スライダーの初期値。
:param cmd: function スライダーの値が変更されたときに呼び出されるコールバック関数。デフォルトは値をプリントする関数です。
:returns: matplotlib.widgets.Slider 作成されたスライダーオブジェクト。
"""
ax = self.plt.axes(box, facecolor = axcolor)
slider = Slider(ax, label, min, max, valinit = init)
def update(val):
print(f"Variable {label} updated to {slider.val}")
if cmd is None:
cmd = update
slider.on_changed(cmd)
self.sliders.append(slider)
return slider