"""
Tkinter GUIアプリケーションの基底モジュール。
このモジュールは、`tkApplication` を継承し、Tkinterベースのグラフィカルユーザーインターフェース (GUI)
アプリケーションを構築するための共通機能を提供します。
ウィンドウの作成、ジオメトリ管理、メニューやツールバーの構築、設定ダイアログの表示、
開発者向けデバッグ機能などが含まれます。
関連リンク:
:doc:`tkapplication_gui_usage`
"""
import os
import subprocess
import sys
import tkinter
from tkinter import ttk
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from tklib.tkutils import find_executable_path, get_os, split_file_path
from tklib.tkparams import tkParams
from tklib.tkapplication import tkApplication
import tklib.tkgui.tktkinter as tktkinter
#=========================
# Application base class
#=========================
[ドキュメント]
class tkApplication_GUI(tkApplication):
"""
Tkinter GUIアプリケーションの基底クラス。
このクラスは `tkApplication` を継承し、TkinterベースのGUIアプリケーションに特化した
機能を提供します。ウィンドウの管理、ウィジェット変数の操作、標準的なGUI要素
(メニュー、ツールバー、ペイン、ダイアログなど)の作成と操作をサポートします。
"""
def __init__(self, usage_str = "", _globals = None, locals = None, use_user_inifile = False, **args):
"""
tkApplication_GUIクラスのコンストラクタ。
基底クラス `tkApplication` の初期化に加え、Tkinterウィジェット変数を
管理するための `tkParams` オブジェクト `self.tkvars` を初期化します。
:param usage_str: str - アプリケーションの利用方法を示す文字列。
:param _globals: dict | None - アプリケーションで使用するグローバル変数辞書。
:param locals: dict | None - アプリケーションで使用するローカル変数辞書。
:param use_user_inifile: bool - ユーザーINIファイルを使用するかどうか。
:param args: dict - その他のキーワード引数。
"""
super().__init__(usage_str = usage_str, _globals = _globals, locals = locals,
use_user_inifile = use_user_inifile, **args)
# self.params = tkParams()
# self.argv = sys.argv
# self.script_path = sys.argv[0]
# tkinter widget variables
self.tkvars = tkParams()
# self.update(**args)
def __del__(self):
"""
tkApplication_GUIクラスのデストラクタ。
基底クラスのデストラクタを呼び出します。
"""
super().__del__()
# pass
def __str__(self):
"""
オブジェクトの文字列表現を返す。
:returns: str - クラスのパスを示す文字列。
"""
return self.ClassPath()
[ドキュメント]
def get_tkvars_dict(self):
"""
Tkinterウィジェット変数を辞書形式で取得する。
`self.tkvars` オブジェクトが保持する全てのウィジェット変数を辞書として返します。
:returns: dict - Tkinterウィジェット変数の辞書。
"""
return self.tkvars.get_param_dict()
[ドキュメント]
def get_tkvar(self, key, defval = None):
"""
指定されたキーのTkinterウィジェット変数の値を取得する。
キーが存在しない場合は、指定されたデフォルト値で初期化してから取得します。
:param key: str - 取得するウィジェット変数のキー。
:param defval: Any | None - キーが存在しない場合に設定するデフォルト値。
:returns: Any - 指定されたキーのウィジェット変数オブジェクト。
"""
if self.tkvars.get(key, None) is None:
setattr(self.tkvars, key, defval)
# self.tkvars[key] = defval
return self.tkvars.get(key)
[ドキュメント]
def mainloop(self):
"""
Tkinterイベントループを開始する。
アプリケーションのGUIがユーザーからの入力を待機し、イベントを処理するための
メインループを開始します。
"""
self.root_window.mainloop()
[ドキュメント]
def get_screen_size(self):
"""
画面のサイズ(幅と高さ)を取得する。
:returns: tuple[int, int] - 画面の幅と高さ。
"""
return self.root_window.winfo_screenwidth(), self.root_window.winfo_screenhight()
[ドキュメント]
def get_geometry(self, window = None):
"""
ウィンドウのジオメトリ文字列と個別の値を取得する。
ウィンドウのジオメトリ(例: "WxH+X+Y")を解析し、幅、高さ、X座標、Y座標を返します。
:param window: tkinter.Tk | tkinter.Toplevel | None - ジオメトリを取得する対象ウィンドウ。Noneの場合はルートウィンドウ。
:returns: tuple[str, int, int, str | None, str | None] - ジオメトリ文字列、幅、高さ、X座標、Y座標。
"""
if window is None:
window = self.root_window
geo = window.geometry()
if 'x' in geo:
w, h = geo.split('x')
if '+' in h:
h, x0, y0 = h.split('+')
return geo, int(w), int(h), x0, y0
return geo, int(w), int(h), None, None
[ドキュメント]
def set_geometory(self, window = None, geo = None, w = None, h = None, x0 = None, y0 = None):
"""
ウィンドウのジオメトリを設定する。
ジオメトリ文字列、または幅、高さ、X座標、Y座標の組み合わせを用いて
ウィンドウの位置とサイズを設定します。
:param window: tkinter.Tk | tkinter.Toplevel | None - ジオメトリを設定する対象ウィンドウ。Noneの場合はルートウィンドウ。
:param geo: str | None - ジオメトリ文字列(例: "800x600+100+50")。指定された場合、他のパラメータは無視されます。
:param w: int | None - ウィンドウの幅。
:param h: int | None - ウィンドウの高さ。
:param x0: int | None - ウィンドウのX座標。
:param y0: int | None - ウィンドウのY座標。
"""
if window is None:
window = self.root_window
if geo is not None:
window.geometry(geo)
elif h is None:
window.geometry(w)
elif x0 is None:
window.geometry("{}x{}".format(w, h))
else:
window.geometry("{}x{}+{}+{}".format(w, h, x0, y0))
print("set_geometory:", self.get_geometry())
[ドキュメント]
def dialog_setup(self, title = 'Setup', parent = None,
entry_width = 30, button_width = 4, edit_button_width = 2, shell_button_width = 0,
widgets = 'editor_path|confirm_on_exit|debug_mode',
font_size = 10,
is_print = False):
"""
アプリケーションの設定ダイアログを表示する。
`tktkinter.tkSetupDialog` を呼び出し、アプリケーションの設定項目を
ユーザーが変更できるダイアログを生成します。
:param title: str - ダイアログのタイトル。
:param parent: tkinter.Widget | None - ダイアログの親ウィジェット。Noneの場合はルートウィンドウ。
:param entry_width: int - エントリウィジェットの幅。
:param button_width: int - ボタンウィジェットの幅。
:param edit_button_width: int - 編集ボタンの幅。
:param shell_button_width: int - シェルボタンの幅。
:param widgets: str - ダイアログに表示するウィジェットのキーを '|' で区切った文字列。
:param font_size: int - ダイアログ内のフォントサイズ。
:param is_print: bool - デバッグ情報を出力するかどうか。
"""
if parent is None:
parent = self.root_window
tktkinter.tkSetupDialog(parent, app = self, title = title,
entry_width = entry_width, button_width = button_width, edit_button_width = edit_button_width,
shell_button_width = shell_button_width,
widgets = widgets,
font_size = font_size,
is_print = is_print)
[ドキュメント]
def on_closing(self, do_confirm = None):
"""
ウィンドウが閉じられる際の処理を行う。
ウィンドウのジオメトリを保存し、確認ダイアログの表示有無に応じて
アプリケーションを終了します。
:param do_confirm: bool | None - 終了時に確認ダイアログを表示するかどうか。Noneの場合は `configparams` の設定に従う。
"""
self.root_window_geometry = self.root_window.geometry()
if do_confirm is None:
do_confirm = self.configparams.get('confirm_on_exit', True)
print("")
print("on_closing:")
print(" geometry :", self.root_window_geometry)
# print(" confirm_on_exit:", self.configparams.confirm_on_exit)
try:
panes = self.main_pane.panes()
# self.left_pane_width = self.main_pane.paneconfig(panes[0], cnf = 'width')
# self.left_pane_height = self.main_pane.paneconfig(panes[0], cnf = 'height')
except:
pass
if not do_confirm:
# print(" confirm?(1):", do_confirm, type(do_confirm))
self.root_window.destroy()
else:
# print(" confirm?(2):", do_confirm, type(do_confirm))
if tktkinter.dialog_okcancel(self, "Quit", "Do you want to quit?"):
self.root_window.destroy()
[ドキュメント]
def PanedWindow1(self, main_pane_args = {}):
"""
1つのペインを持つPanedWindowを作成する。
ルートウィンドウに単一のペインを持つ `tkinter.PanedWindow` を作成し、
それを `self.main_pane` に設定します。
:param main_pane_args: dict - `tkinter.PanedWindow` に渡す引数の辞書。
:returns: tkinter.PanedWindow - 作成されたPanedWindowウィジェット。
"""
main_pane = tkinter.PanedWindow(self.root_window,
sashwidth = main_pane_args.get('sashwidth', 2)
)
# left_notebook = tkinter.ttk.Notebook(main_pane)
# main_pane.add(left_notebook)#, width = left_pane_width)
main_pane.pack(expand = True, fill = tkinter.BOTH, side = tkinter.TOP)
self.main_pane = main_pane
# return main_pane, left_notebook
return main_pane
[ドキュメント]
def PanedWindow2(self, main_pane_args = {}, left_pane_args = {}, right_pane_args = {}):
"""
2つのペイン(左右)を持つPanedWindowを作成する。
ルートウィンドウに左右に分割された `tkinter.PanedWindow` を作成し、
それぞれのペインに `tkinter.ttk.Notebook` を配置します。
これらを `self.main_pane`, `self.left_notebook`, `self.right_notebook` に設定します。
:param main_pane_args: dict - メインPanedWindowに渡す引数の辞書。
:param left_pane_args: dict - 左ペイン(Notebook)に渡す引数の辞書。
:param right_pane_args: dict - 右ペイン(Notebook)に渡す引数の辞書。
:returns: list[tkinter.PanedWindow | tkinter.ttk.Notebook] - 作成された [メインペイン, 左ノートブック, 右ノートブック] のリスト。
"""
main_pane = tkinter.PanedWindow(self.root_window,
sashwidth = main_pane_args.get('sashwidth', 2)
)
width = left_pane_args.get('width', None)
if width is None:
width = 300
# left_notebook = tkinter.Frame(main_pane, width = width)
left_notebook = tkinter.ttk.Notebook(main_pane,
width = width
)
# left_notebook.pack(expand = True, fill = tkinter.BOTH)
width = right_pane_args.get('width', None)
if width is None:
width = 300
# right_notebook = tkinter.Frame(main_pane, width = width)
right_notebook = tkinter.ttk.Notebook(main_pane,
width = width
)
# right_notebook.pack()
main_pane.add(left_notebook)#, width = left_pane_width)
main_pane.add(right_notebook)#, width = right_pane_width)
main_pane.pack(expand = True, fill = tkinter.BOTH, side = tkinter.TOP)
self.main_pane = main_pane
self.left_notebook = left_notebook
self.right_notebook = right_notebook
return [main_pane, left_notebook, right_notebook]
[ドキュメント]
def add_root_panes(self, root = None, type = '', sashwidth = 2, left_pane_width = 50):
"""
ルートウィンドウに指定されたタイプのペインを追加する。
'pane1' タイプの場合は単一のNotebook、'pane2' タイプの場合は左右に分割された
PanedWindow(それぞれNotebookを含む)を作成します。
:param root: tkinter.Tk | None - ペインを追加するルートウィンドウ。Noneの場合は `self.root_window`。
:param type: str - 作成するペインのタイプ ('', 'pane1', 'pane2')。
:param sashwidth: int - PanedWindowのサッシュ(仕切り)の幅。
:param left_pane_width: int - 'pane2' タイプの場合の左ペインの幅。
:returns: list[tkinter.Widget] - 作成されたペインのリスト。
"""
if root is None:
root = self.root_window
if type == 'pane1':
main_pane = tkinter.ttk.Notebook(root)
# main_pane = tkinter.PanedWindow(root, sashwidth = sashwidth)
main_pane.pack(expand = True, fill = tkinter.BOTH, side = tkinter.TOP)
return [main_pane]
elif type == 'pane2':
main_pane, left_pane, right_pane \
= self.PanedWindow2(main_pane_args = {'sashwidth': sashwidth},
left_pane_args = {'width': left_pane_width})
return [main_pane, left_pane, right_pane]
elif type == '':
return [self.root_window]
self.terminate(f"Error in tkapplication_gui.add_root_panes(): Invalid type [{type}]")
[ドキュメント]
def move_top(self, f = True):
"""
ウィンドウを最前面に移動するかどうかを設定する。
`self.root_window` の `"-topmost"` 属性を変更して、ウィンドウが
他のウィンドウの上に表示されるように設定します。
:param f: bool - Trueの場合、ウィンドウを最前面に表示します。Falseの場合、通常の表示に戻します。
"""
self.root_window.attributes("-topmost", f)
[ドキュメント]
def create_subwindow(self):
"""
新しいトップレベルのサブウィンドウを作成する。
親ウィンドウ `self.root_window` を持つ `tkinter.Toplevel` ウィンドウを作成します。
:returns: tkinter.Toplevel - 作成されたトップレベルウィンドウ。
"""
w = tkinter.Toplevel(master = self.root_window)
tkinter.Frame(w).pack()
return w
[ドキュメント]
def create_window(self, title = None, type = '', geometry = None, minsize = None,
iconfile = None, sashwidth = 2, left_pane_width = 50, icon_path = None,
relief = 'ridge', borderwidth = 2, bg = 'white', default_font = None):
"""
Tkinterのメインウィンドウ(ルートウィンドウ)を作成する。
ウィンドウのタイトル、ジオメトリ、最小サイズ、アイコン、ボーダーなどの外観を設定し、
`WM_DELETE_WINDOW` プロトコルハンドラを設定します。
:param title: str | None - ウィンドウのタイトル。
:param type: str - ウィンドウのタイプ(現在のところ使用されていないが互換性のために残されている)。
:param geometry: str | None - ウィンドウの初期ジオメトリ文字列(例: "800x600+100+50")。
:param minsize: tuple[int, int] | None - ウィンドウの最小サイズ (幅, 高さ)。
:param iconfile: str | None - ウィンドウアイコンファイルのパス。
:param sashwidth: int - PanedWindowのサッシュ幅(関連するメソッドに渡されるが、このメソッド自体では使用されない)。
:param left_pane_width: int - 左ペインの初期幅(関連するメソッドに渡されるが、このメソッド自体では使用されない)。
:param icon_path: str | None - ウィンドウアイコンファイルのパス(`iconfile` と同様)。
:param relief: str - ウィンドウの枠の種類(例: 'ridge', 'sunken', 'flat')。
:param borderwidth: int - ウィンドウの枠の幅。
:param bg: str - ウィンドウの背景色。
:param default_font: tuple[str, int] | None - アプリケーション全体のデフォルトフォント (フォント名, サイズ)。
:returns: tkinter.Tk - 作成されたルートウィンドウ。
"""
root = tkinter.Tk()
if iconfile:
if not os.path.isfile(iconfile):
print(f"\nWarning: Icon file [{iconfile}] does not exist.\n")
else:
root.iconbitmap(default = iconfile)
# ('FixedSys', 14)
if default_font is not None:
root.option_add('*font', default_font)
if geometry:
root.geometry(geometry)
# root.resizable(False, False)
if minsize:
root.minsize(*minsize)
if title is not None:
root.title(title)
if icon_path:
root.iconbitmap(default = icon_path)
root.configure(borderwidth = borderwidth, relief = relief, bg = bg)
root.grid()
root.protocol("WM_DELETE_WINDOW", lambda: self.on_closing())
self.root_window = root
return root
[ドキュメント]
def get_editor(self):
"""
デフォルトのエディタのパスを取得する。
アプリケーションの設定 (`configparams`)、環境変数、および一般的なエディタのパスを検索して、
最初に見つかったエディタの実行可能ファイルのパスを返します。
:returns: str - エディタの実行可能ファイルのパス。見つからない場合は空文字列。
"""
if self.configparams.get('editor_path', None):
return self.configparams.editor_path
# editor_paths = [] # 使用されていないが、元のコードではリスト化を試みていた痕跡があるためコメントアウト
for key in ['EDITOR_PATH', 'tkEDITOR_PATH', 'EDITOR']:
if key in os.environ:
return os.environ[key]
# editor_paths.append(os.environ[key]) # 現在のロジックでは到達しない
return ''
[ドキュメント]
def print_tkvars_info(app, cparams, tkvars):
"""
Tkinterウィジェット変数の情報をコンソールに出力する。
`tkvars` オブジェクト内の各変数について、そのキーと値を(可能であれば `get()` メソッドを使って)
標準エラー出力に警告として表示します。
:param app: tkApplication_GUI - アプリケーションインスタンス。
:param cparams: tklib.tkparams.tkParams - 設定パラメータオブジェクト。
:param tkvars: tklib.tkparams.tkParams - Tkinterウィジェット変数を保持するオブジェクト。
"""
app.print_warning("")
app.print_warning("tkvars")
for key in tkvars.keys():
# print(f"tkvars[{key}]=", tkvars[key], type(tkvars[key]))
if type(tkvars[key]) is list:
app.print_warning(f" {key}:", tkvars[key])
elif tkvars[key] is None:
pass
elif type(tkvars[key]) is int or type(tkvars[key]) is float or type(tkvars[key]) is str:
app.print_warning(f" {key}:", tkvars[key])
else:
try:
app.print_warning(f" {key}:", tkvars[key].get())
except:
app.print_warning(f" {key}:", type(tkvars[key]))
[ドキュメント]
def print_cparams_info(app, cparams, tkvars, copy_tkvars = None):
"""
`cparams` (設定パラメータ) の情報をコンソールに出力する。
`cparams` オブジェクトのパラメータを標準エラー出力に警告として表示します。
必要に応じて `copy_tkvars` コールバックを呼び出し、`tkvars` から `cparams` へ値をコピーします。
:param app: tkApplication_GUI - アプリケーションインスタンス。
:param cparams: tklib.tkparams.tkParams - 設定パラメータオブジェクト。
:param tkvars: tklib.tkparams.tkParams - Tkinterウィジェット変数を保持するオブジェクト。
:param copy_tkvars: callable | None - `tkvars` から `cparams` に値をコピーするためのコールバック関数。
"""
app.print_warning("")
app.print_warning("cparams")
if copy_tkvars is not None:
copy_tkvars(app, cparams, tkvars)
cparams.print_parameters_warning()
[ドキュメント]
def print_config_info(app, config, tkvars, copy_tkvars = None):
"""
`config` オブジェクトの情報をコンソールに出力する。
`config` オブジェクトのパラメータを標準エラー出力に警告として表示します。
必要に応じて `copy_tkvars` コールバックを呼び出し、`tkvars` から `config` へ値をコピーします。
:param app: tkApplication_GUI - アプリケーションインスタンス。
:param config: tklib.tkparams.tkParams - 設定オブジェクト。
:param tkvars: tklib.tkparams.tkParams - Tkinterウィジェット変数を保持するオブジェクト。
:param copy_tkvars: callable | None - `tkvars` から `config` に値をコピーするためのコールバック関数。
"""
app.print_warning("")
app.print_warning("config")
if copy_tkvars is not None:
copy_tkvars(app, config, tkvars)
config.print_parameters_warning()
[ドキュメント]
def create_editor_frame(app, frame,
head_label_args = {'text': 'Path:'},
entry_width = 60,
eval_button_args = [],
show_path_select = True,
):
"""
ファイルパス選択とテキスト編集機能を備えたエディタフレームを作成する。
`tktkinter.Editor` ウィジェットを使用して、ファイルパス入力欄、パス選択ボタン、
テキストエリア、および実行ボタンを含むフレームを作成します。
実行ボタンにはデフォルトで `evaluate` 関数が割り当てられます。
:param app: tkApplication_GUI - アプリケーションインスタンス。
:param frame: tkinter.Frame - エディタフレームを配置する親フレーム。
:param head_label_args: dict - ヘッダーラベルに渡す引数の辞書。
:param entry_width: int - エントリウィジェットの幅。
:param eval_button_args: dict - 評価(実行)ボタンに渡す引数の辞書。
:param show_path_select: bool - パス選択ウィジェットを表示するかどうか。
:returns: tktkinter.Editor - 作成されたエディタウィジェット(tktkinter.Editorクラスのインスタンス)。
"""
cparams = app.get_params()
config = app.config
ctkvars = app.tkvars
tkvars = ctkvars.get_param_dict()
def path_button_click():
"""ファイル選択ボタンがクリックされた時の処理。"""
tktkinter.path_button_click(app, tkvars['target_file'],
file_type = [('all', '*.*')], ini_dir = '.')
s = ''
with open(tkvars['target_file'].get(), 'r') as fp:
s = fp.read()
tkvars['edit_text'].delete('1.0', 'end')
tkvars['edit_text'].insert('end', s)
if eval_button_args.get("command", None) is None:
use_custom_command = True
else:
use_custom_command = False
if show_path_select:
entry_args = {'textvariable': ['target_file', tkinter.StringVar()], 'width': entry_width}
button_args = {'text': 'path', 'width': 5, 'command': lambda: path_button_click()}
else:
head_label_args = {}
entry_args = {}
button_args = {}
Editor_frame = tktkinter.Editor(app, frame,
frame_args = {'bg': 'white'},
head_label_args = head_label_args,
entry_args = entry_args,
# entry_args = {'textvariable': obj['editor'], 'width': None},
# button_args = {'text': 'eval', 'width': 5},
button_args = button_args,
eval_button_args = eval_button_args,
borderwidth = 2, relief = 'groove',
)
Editor_frame.pack(fill = tkinter.BOTH, expand = True)
def help_eval():
"""評価環境のグローバル変数を表示するヘルパー関数。"""
app.print_warning("Global variables")
dict = app.globals
for key in dict.keys():
app.print_warning(f" {key}: {dict[key]}")
def evaluate(Text):
"""
テキストエリアのコードを評価(実行)する。
:param Text: tkinter.Text - 評価するコードが含まれるTextウィジェット。
"""
text = Text.get(1.0, "end")
app.print_warning("")
app.print_warning("Run:")
app.print_warning(f"> {text}\n>> ")
redirects_original = app.redirects
if 'stdout' not in app.redirects:
app.redirects.append("stdout")
ret = exec(text, app.globals, {"app": app, "cparams": cparams, "config": config, "tkvars": tkvars, "help": help_eval} )
app.redirects = redirects_original
if ret is None:
app.print_warning("")
else:
app.print_warning(f"ret={ret}")
return
"""
# print(text)
# print(exec(text))
lines = text.split('\n')
for l in lines:
if l is None:
break
l.strip()
if l == '':
continue
print(f"> {l}\n>> ", end = '')
ret = exec(l, app.globals, {"app": app, "cparams": cparams, "config": config, "tkvars": tkvars} )
if ret is None:
print("")
else:
print(f"ret={ret}")
"""
tkvars['edit_text'] = Editor_frame.Text
frame.PathFrame = Editor_frame.PathFrame
frame.entry = Editor_frame.entry
frame.eval_button = Editor_frame.eval_button
frame.Text = Editor_frame.Text
if use_custom_command and frame.eval_button:
frame.eval_button.configure(command = lambda: evaluate(frame.Text))
return Editor_frame
[ドキュメント]
def create_editor_tab(app, config, cparams, pane, title,
entry_width = 60,
eval_button_args = {}
):
"""
ノートブックウィジェット内にエディタ機能を持つタブを作成する。
`create_editor_frame` を使用して、指定されたタイトルで新しいタブを作成し、
そこにエディタフレームを配置します。
:param app: tkApplication_GUI - アプリケーションインスタンス。
:param config: tklib.tkparams.tkParams - 設定オブジェクト。
:param cparams: tklib.tkparams.tkParams - 設定パラメータオブジェクト。
:param pane: tkinter.ttk.Notebook - タブを追加するノートブックウィジェット。
:param title: str - 作成するタブのタイトル。
:param entry_width: int - エディタのエントリウィジェットの幅。
:param eval_button_args: dict - 評価(実行)ボタンに渡す引数の辞書。
:returns: tktkinter.Editor - 作成されたエディタウィジェット(tktkinter.Editorクラスのインスタンス)。
"""
title = app.p(title)
frame = tktkinter.Frame(app, pane, bg='dim gray')
pane.add(frame, text = title + ' ')
Editor_frame = app.create_editor_frame(frame, entry_width = entry_width, eval_button_args = eval_button_args)
return Editor_frame
[ドキュメント]
def create_development_tab(app, config, cparams, parent_notebook, copy_tkvars = None):
"""
アプリケーションの開発者向けデバッグタブを作成する。
Pythonパス情報、各種設定パラメータ(`app`, `cparams`, `tkvars`, `config`,
環境変数、スクリプト変数)を表示・デバッグするためのボタン、
およびコードを実行できるエディタフレームを含むタブを作成します。
:param app: tkApplication_GUI - アプリケーションインスタンス。
:param config: tklib.tkparams.tkParams - 設定オブジェクト。
:param cparams: tklib.tkparams.tkParams - 設定パラメータオブジェクト。
:param parent_notebook: tkinter.ttk.Notebook - タブを追加する親ノートブックウィジェット。
:param copy_tkvars: callable | None - `tkvars` から `cparams` や `config` に値をコピーするためのコールバック関数。
:returns: tkinter.Frame - 作成された開発タブのフレーム。
"""
config = app.config
ctkvars = app.tkvars
tkvars = ctkvars.get_param_dict()
if app.get('hidden_params', None) is None:
app.hidden_params = tkParams()
PYTHONPATH = os.environ.get('PYTHONPATH', '')
if get_os() == 'Windows':
libpaths = PYTHONPATH.split(';')
elif ':' in PYTHONPATH:
libpaths = PYTHONPATH.split(':')
else:
libpaths = PYTHONPATH.split(';')
app.hidden_params.libpaths = []
for path in libpaths:
if 'tklib' in path or 'tkProg' in path or 'tkprog' in path:
app.hidden_params.libpaths.append(path)
page1_frame = tktkinter.Frame(app, parent_notebook, bg = 'dim gray')
page1_frame.pack()
parent_notebook.add(page1_frame, text = app.p('Development') + ' ')
notebook_frame = page1_frame
# Script path frame
path_grid_frame = tkinter.Frame(page1_frame)
tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame,
tkvars, varname = 'program_path',
file_type = [("python", "*.py"), ("Text", "*.txt;*.ini"), ("All", "*.*")],
working_dir = app.script_dir,
is_print = True, igridrow = 0)
for i in range(len(app.hidden_params.libpaths)):
path = app.hidden_params.libpaths[i]
# varname = f'lib{i+1}'
tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame,
tkvars, varname = f'lib{i+1}',
file_type = [("python", "*.py"), ("Text", "*.txt;*.ini"), ("All", "*.*")],
working_dir = app.hidden_params.libpaths[i],
is_print = True, igridrow = i + 1)
# Maintenance buttons
button_frame2 = tkinter.Frame(page1_frame)
button1 = tktkinter.Button(app, button_frame2, text = 'app', width = 8, font = ("", 16),
command = lambda: app.print_attributes_warning(print_header = True))
button1.pack(side = tkinter.LEFT)
button2 = tktkinter.Button(app, button_frame2, text = 'cparams', width = 8, font = ("", 16),
command = lambda: app.print_cparams_info(cparams, tkvars, copy_tkvars = copy_tkvars))
button2.pack(side = tkinter.LEFT)
button3 = tktkinter.Button(app, button_frame2, text = 'tkvars', width = 8, font = ("", 16),
command = lambda: app.print_tkvars_info(cparams, tkvars))
button3.pack(side = tkinter.LEFT)
button4 = tktkinter.Button(app, button_frame2, text = 'config', width = 8, font = ("", 16),
command = lambda: app.print_config_info(config, tkvars, copy_tkvars = copy_tkvars))
button4.pack(side = tkinter.LEFT)
button_frame2.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)
# Maintenance buttons 2
button_frame3 = tkinter.Frame(page1_frame)
button1 = tktkinter.Button(app, button_frame3, text = 'env', width = 8, font = ("", 16),
command = lambda: app.print_dict_warning(os.environ, header = 'Environment variables'))
button1.pack(side = tkinter.LEFT)
svars = app.get('svars', None)
if svars:
button2 = tktkinter.Button(app, button_frame3, text = 'app vars', width = 8, font = ("", 12),
command = lambda: app.print_dict_warning(svars.get_param_dict(), header = 'Script variables'))
button2.pack(side = tkinter.LEFT)
s_engine = app.get('s_engine', None)
if s_engine:
button3 = tktkinter.Button(app, button_frame3, text = 'scr vars', width = 8, font = ("", 12),
command = lambda: app.print_dict_warning(s_engine.vars, header = 'Script variables'))
button3.pack(side = tkinter.LEFT)
button_frame3.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2)
editor_frame = app.create_editor_frame(page1_frame, show_path_select = False,
eval_button_args = { 'text': 'eval', 'width': 4, "command": None },
)
return notebook_frame
[ドキュメント]
def get_editors(self, additional_list = [], filename_only = False):
"""
システムで利用可能なエディタの実行可能ファイルのパスリストを取得する。
オペレーティングシステムに応じた一般的なエディタ、環境変数、および追加で指定されたエディタを検索し、
重複を排除して実行可能ファイルのパスを返します。
:param additional_list: list[str] - 検索対象に追加するエディタ名のリスト。
:param filename_only: bool - ファイル名のみを返すかどうか。Trueの場合、パスではなく実行ファイル名のみを返します。
:returns: list[str] - 利用可能なエディタの実行可能ファイルのパスのリスト。
"""
os_name = get_os()
if os_name == 'Windows':
elist = ['code', 'subl', 'sublime_text', 'atom', 'pspad', 'emeditor', 'uedit64',
'notepad++', 'notepad', 'emacs', 'xemacs', 'gvim', 'vim', 'vi'] + additional_list
elif os_name == 'Linux':
elist = ['code', 'gedit', 'gvim', 'kate', 'subl', 'notepadqq', 'nano', 'atom', 'emacs', 'xemacs', 'vim', 'vi'] + additional_list
else:
elist = ['code', 'Xcode', 'gvim', 'subl', 'atom', 'bbedit_tool', 'mate', 'TextEdit', 'emacs', 'xemacs', 'vim', 'vi'] + additional_list
editor_paths = []
for key in elist:
path = find_executable_path(key, filename_only = filename_only)
if path and path not in editor_paths:
editor_paths.append(path)
for key in ['EDITOR_PATH', 'tkEDITOR_PATH', 'EDITOR']:
if key in os.environ and os.environ[key] not in editor_paths:
editor_paths.append(os.environ[key])
return editor_paths
[ドキュメント]
def get_start_apps(self, additional_list = [], filename_only = False):
"""
ファイルを開くための「起動」アプリケーションの実行可能ファイルのパスリストを取得する。
オペレーティングシステムに応じた一般的なファイル起動コマンド、および追加で指定された
アプリケーションを検索し、重複を排除して実行可能ファイルのパスを返します。
:param additional_list: list[str] - 検索対象に追加するアプリケーション名のリスト。
:param filename_only: bool - ファイル名のみを返すかどうか。Trueの場合、パスではなく実行ファイル名のみを返します。
:returns: list[str] - ファイルを起動するためのアプリケーションの実行可能ファイルのパスのリスト。
"""
os_name = get_os()
start_paths = []
if os_name == 'Windows':
slist = [] + additional_list
start_paths = ['start']
elif os_name == 'Linux':
slist = ['x-open.sh', 'xdg-open'] + additional_list
else:
slist = ['m-open.sh', 'open'] + additional_list
for key in slist:
path = find_executable_path(key, filename_only = filename_only)
if path and path not in start_paths:
start_paths.append(path)
return start_paths
[ドキュメント]
def get_shells(self, additional_list = [], filename_only = False):
"""
システムで利用可能なシェル(コマンドプロンプト/ターミナル)の実行可能ファイルのパスリストを取得する。
オペレーティングシステムに応じた一般的なシェル、および追加で指定されたシェルを検索し、
重複を排除して実行可能ファイルのパスを返します。
:param additional_list: list[str] - 検索対象に追加するシェル名のリスト。
:param filename_only: bool - ファイル名のみを返すかどうか。Trueの場合、パスではなく実行ファイル名のみを返します。
:returns: list[str] - 利用可能なシェルの実行可能ファイルのパスのリスト。
"""
os_name = get_os()
shell_paths = []
if os_name == 'Windows':
slist = ['cmd', 'wt', 'powershell'] + additional_list
elif os_name == 'Linux':
slist = ['xterm', 'gnome-terminal', 'konsole'] + additional_list
else:
slist = ['xterm', 'gnome-terminal', 'konsole'] + additional_list
for key in slist:
path = find_executable_path(key, filename_only = filename_only)
if path and path not in shell_paths:
shell_paths.append(path)
return shell_paths
[ドキュメント]
def get_filers(self, additional_list = [], filename_only = False):
"""
システムで利用可能なファイルマネージャ(ファイラ)の実行可能ファイルのパスリストを取得する。
オペレーティングシステムに応じた一般的なファイルマネージャ、および追加で指定された
ファイルマネージャを検索し、重複を排除して実行可能ファイルのパスを返します。
:param additional_list: list[str] - 検索対象に追加するファイルマネージャ名のリスト。
:param filename_only: bool - ファイル名のみを返すかどうか。Trueの場合、パスではなく実行ファイル名のみを返します。
:returns: list[str] - 利用可能なファイルマネージャの実行可能ファイルのパスのリスト。
"""
os_name = get_os()
if os_name == 'Windows':
flist = ['explorer'] + additional_list
elif os_name == 'Linux':
flist = ['nautilus', 'thunar', 'pcmanfm', 'dlphin', 'nemo', 'ranger'] + additional_list
else:
flist = ['Finder', 'Path Finder', 'Commander One', 'muCommander', 'nautilus', 'thunar', 'pcmanfm', 'dlphin', 'nemo', 'ranger'] + additional_list
filer_paths = []
for key in flist:
path = find_executable_path(key, filename_only = filename_only)
if path and path not in filer_paths:
filer_paths.append(path)
return filer_paths
[ドキュメント]
def get_external_apps(self, paths, use_default = True, filename_only = False):
"""
外部アプリケーションの実行可能ファイルのパスリストを取得する。
指定されたパス、デフォルトの一般的なアプリケーション、および環境変数を検索し、
重複を排除して実行可能ファイルのパスを返します。`use_default` を `False` にすると、
デフォルトのアプリケーションリストは含まれません。
:param paths: list[str] - 検索対象に追加するアプリケーション名のリスト。
:param use_default: bool - デフォルトのアプリケーションリストを含めるかどうか。
:param filename_only: bool - ファイル名のみを返すかどうか。Trueの場合、パスではなく実行ファイル名のみを返します。
:returns: list[str] - 外部アプリケーションの実行可能ファイルのパスのリスト。
"""
if not use_default:
app_paths = []
for key in paths:
path = find_executable_path(key, filename_only = filename_only)
if (path is None or path == "") and key not in app_paths:
app_paths.append(key)
elif path not in app_paths:
app_paths.append(path)
return app_paths
if get_os() == 'Windows':
app_paths = ['auto', 'start', 'start cmd.exe /K', 'explorer.exe [/n,/e,%(dir)]']
for key in ['code', 'notepad', 'emacs', 'vim', 'powershell', 'python3', 'python2', 'python']:
path = find_executable_path(key)
if path and path not in app_paths:
app_paths.append(path)
else:
app_paths = ['auto']
for key in ['code', 'emacs', 'vim', 'bash', 'tsch', 'python3', 'python2', 'python', 'py']:
path = find_executable_path(key)
if path and path not in app_paths:
app_paths.append(path)
for key in ['EDITOR_PATH', 'tkEDITOR_PATH', 'EDITOR', 'VESTA_PATH']:
if key in os.environ and os.environ[key] not in app_paths:
app_paths.append(os.environ[key])
for key in paths:
path = find_executable_path(key)
if (path is None or path == "") and key not in app_paths:
app_paths.append(key)
elif path not in app_paths:
app_paths.append(path)
return app_paths
[ドキュメント]
def main():
"""
モジュールが直接実行された場合に呼び出される関数。
このモジュールがライブラリであることを示し、直接実行できないことを通知するメッセージを出力します。
"""
print("")
print("This is library, not runnable")
print("")
if __name__ == "__main__":
"""
スクリプトが直接実行された場合に `main()` 関数を呼び出す。
"""
main()