PHYSBO.bayes_gp_gui のソースコード

"""
GUI for bayes_gp_plain.py

概要:
    ガウス過程を用いたベイズ最適化のGUIアプリケーション。
詳細説明:
    このスクリプトは、`bayes_gp_plain2.py` の計算エンジンを操作するための
    グラフィカルユーザーインターフェース(GUI)を提供します。
    ファイルパスの指定、ベイズ最適化のパラメータ設定、グラフ表示、
    およびアプリケーションの一般的な設定変更が可能です。
    Tkinterライブラリを使用して構築されています。
関連リンク:
    :doc:`bayes_gp_gui_usage`
"""
import sys
from sys import exit
import os
import time
import openpyxl
import tkinter
from numpy import exp, log, log10, sin, cos, tan, arcsin, arccos, arctan, sqrt


v = os.environ.get('tklibPath', None)
if v:
    tklib_path = v
else:
    script_path = sys.argv[0]
    tkProgRoot  = os.path.join(script_path, '../../..')
    tklib_path  = os.path.abspath(os.path.join(tkProgRoot, 'tklib/python'))

print(f"Add [{tklib_path}] to PYTHONPATH by sys.path.append()")
sys.path.append(tklib_path)


from tklib.tkutils import getarg, getintarg, getfloatarg, pint, pfloat, terminate, get_os, split_file_path, get_dirname
from tklib.tkinifile import tkIniFile
from tklib.tkparams import tkParams
from tklib.tkgui.tkapplication_gui import tkApplication_GUI
import tklib.tkgui.tktkinter as tktkinter

import bayes_gp_plain as c_engine


usage_str = '''
"(i)   usage: python {}".format(sys.argv[0])
'''[1:-1]


#==============================================
# Global bariables
#==============================================

prog_name = 'Bayes/GP GUI'
version = [1, 3, 1]


#=============================
# Treat argments
#=============================
[ドキュメント] def usage(app: tkApplication_GUI): """ 概要: アプリケーションの使用方法をコマンドラインに出力します。 詳細説明: `app` オブジェクトに格納されている `usage_str` を解析し、 各行を標準出力に表示します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 """ # cparams = app.get_params() # app.usage(infile = cparams.infile) for s in app.usage_str.split('\n'): cmd = 'print({})'.format(s.rstrip()) eval(cmd)
[ドキュメント] def initialize(app: tkApplication_GUI, config: tkIniFile): """ 概要: アプリケーションの初期設定とデフォルト値を定義します。 詳細説明: ファイルタイプ、リソースディレクトリ、および設定可能なパラメータ (言語、デバッグモード、ウィンドウサイズなど)のデフォルト値を設定します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 """ #================================ # Global variables #================================ ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() # Non-configurable configuration app.prm_file_type = [('prm file', '*.prm')] app.data_file_type = [('data file', '*.csv')] app.resource_dir = os.path.join(app.script_dir, 'resource') # Configurable configuration config = app.config config.lang = 'en' config.debug = 0 config.print_level = 0 config.confirm_on_exit = True config.minsize = [200, 200] config.geometry = "507x447" config.left_pane_width = 500 config.message_box_width = 100 config.message_box_height = 4 config.head_label_width = 10 config.entry_width = 30 config.button_width = 12 # Define var types in config for auto type conversion in config.read_parameters() config.editor_path = '' config.infile = '' config.outfile = '' config.outresfile = '' config.score_mode = 'EI' config.program_path = ''
[ドキュメント] def update_vars(app: tkApplication_GUI, cparams: tkParams): """ 概要: コマンドライン引数に基づいて計算パラメータを更新します。 詳細説明: 現在のコードでは特にコマンドライン引数を処理していませんが、 `getarg` のコメントアウトから、将来的に引数を処理する可能性を示唆しています。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 """ argv = app.argv
# if len(argv) <= 1: # app.terminate(usage = usage) # cparams.infile = getarg(1, cparams.infile)
[ドキュメント] def create_menu(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, root_window: tkinter.Tk) -> tkinter.Menu: """ 概要: アプリケーションのメニューバーを作成します。 詳細説明: 「ファイル」メニュー(開く、終了)と「ツール」メニュー(設定)を追加し、 それぞれのコマンドとショートカットを割り当てます。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param root_window: tkinter.Tk: メインウィンドウオブジェクト。 戻り値 (Returns): :returns: tkinter.Menu: 作成されたメニューバーオブジェクト。 """ menu_bar = app.create_menu() menu_file = tktkinter.Menu(app, menu_bar, tearoff = 0) menu_file.add_command(label = app.p('Open'), accelerator = 'Ctrl+O', command = lambda: data_path_button_click(app, tkvars)) menu_file.add_command(label = app.p('exit'), accelerator='Alt+E', command = lambda: app.on_closing()) menu_bar.add_cascade(label = app.p('File'), menu = menu_file) menu_tool = tkinter.Menu(menu_bar, tearoff = 0) menu_tool.add_command(label = app.p('Setup'), accelerator = 'Ctrl+u', command = lambda e: app.dialog_setup( widgets = 'editor_path|confirm_on_exit|debug_mode')) menu_bar.add_cascade(label = app.p('Tool'), menu = menu_tool) # menu_bar.bind_all("<Alt-o>", onOpen) menu_bar.bind_all("<Alt-e>", lambda e: app.on_closing()) menu_bar.bind_all("<Alt-u>", lambda e: app.dialog_setup( widgets = 'editor_path|python3_path|python2_path|perl_path|confirm_on_exit|debug_mode')) return menu_bar
[ドキュメント] def create_toolbar(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, root_window: tkinter.Tk): """ 概要: アプリケーションのツールバーを作成します。 詳細説明: 「Setup」、「Edit ini file」、「言語選択コンボボックス」、「Exit」ボタンを ツールバーに追加し、それぞれの機能を定義します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param root_window: tkinter.Tk: メインウィンドウオブジェクト。 """ ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() config = app.configparams def toolbar_clickevent(event): pass tool_bar = app.create_toolbar(bg = 'blue') setupButton = tktkinter.Button(app, tool_bar, text = "Setup", font = ("", 10), command = lambda: app.dialog_setup( entry_width = 50, button_width = 10, edit_button_width = 10, shell_button_width = 0, widgets = 'editor_path|confirm_on_exit|debug_mode', is_print = True)) setupButton.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0) def edit_inifile(): editor = config.get("editor_path", None) if editor is None== '' or editor == '': tktkinter.dialog_okcancel(app, title = app.p('Error'), message = 'editor_path is not specified.') return tktkinter.execute_command(app, config.editor_path, working_dir = '.', is_print = True, files = [config.inifile]) edit_ini_Button = tktkinter.Button(app, tool_bar, text = 'Edit ini file', font = ("", 10), command = edit_inifile) edit_ini_Button.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0) def lang_sel_change(e): config.lang = tkvars['lang_combobox'].get() phrases = {'WillApplyUponReboot': {'ja': f'日本語に変更されました。再起動後に有効になります', 'en': f'Changed to English. Will be applied after reboot' } } tktkinter.dialog_okcancel(app, title = app.p('Quit'), message = app.p('WillApplyUponReboot', phrases = phrases)) tkvars['lang'] = tkinter.StringVar(value = config.lang) # optionmenu = tkinter.OptionMenu(tool_bar, tool_bar, 'ja', 'en') # optionmenu.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0) combobox = tkinter.ttk.Combobox(tool_bar, values = ('ja', 'en'), width = 2) combobox.set(tkvars['lang'].get()) combobox.bind('<<ComboboxSelected>>', lang_sel_change) combobox.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0) tkvars['lang_combobox'] = combobox exitButton = tktkinter.Button(app, tool_bar, text = 'Exit', font = ("", 10), command = lambda: app.on_closing(), anchor = tkinter.NW) exitButton.pack(side = tkinter.LEFT, anchor = 'w', padx = 1, pady = 0)
[ドキュメント] def copy_tkvars(app: tkApplication_GUI, cparams: tkParams, tkvars: dict): """ 概要: GUIウィジェットの変数(tkvars)の値を計算パラメータオブジェクトと設定パラメータオブジェクトにコピーします。 詳細説明: 特定のキーに対応するTkinter変数の値を取得し、`cparams` (計算パラメータ) および `config` (アプリケーション設定) の対応する属性に設定します。 グラフのサイズも処理します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param tkvars: dict: Tkinterウィジェット変数を格納する辞書。 """ config = app.configparams # for key in ["script_path", "prmpath", "infile", "outfile", "max_num_probes", "num_search_each", "num_rand_basis", "interval", "score_mode"]: for key in ["program_path", "infile", "outfile", "nx_2D", "ny_2D", "max_num_probes", "num_search_each", "num_rand_basis", "interval", "score_mode", "random_seed", "standardize", "fontsize", "legend_fontsize"]: cparams.set_attr(key, tkvars[key].get()) for key in ["program_path", "infile", "outfile", "outresfile","fontsize", "legend_fontsize"]: config.set_attr(key, tkvars[key].get()) cparams.set_attr('figsize', [tkvars['fig_width'].get(), tkvars['fig_height'].get()])
[ドキュメント] def copy_config(app: tkApplication_GUI, cparams: tkParams, config: tkIniFile): """ 概要: アプリケーション設定パラメータを計算パラメータにコピーします。 詳細説明: `config` オブジェクトのキーが `cparams` オブジェクトにも存在する場合、 その値を `cparams` にコピーします。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 """ keys0 = config.__dict__.keys() for key in cparams.__dict__.keys(): if key in keys0: cparams.set_attr(key, cparams.get(key, None))
[ドキュメント] def create_graph_tab(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, parent_notebook: tkinter.ttk.Notebook) -> tkinter.Frame: """ 概要: グラフ設定用のタブページを作成します。 詳細説明: グラフの幅、高さ、フォントサイズ、凡例のフォントサイズを設定するための ウィジェットを配置します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param parent_notebook: tkinter.ttk.Notebook: 親となるノートブックウィジェット。 戻り値 (Returns): :returns: tkinter.Frame: 作成されたタブページフレーム。 """ config = app.configparams ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() page1_frame = tktkinter.Frame(app, parent_notebook, bg = 'dim gray') page1_frame.pack() parent_notebook.add(page1_frame, text = app.p('Graph')) notebook_frame = page1_frame # Graph parameter block graph_grid_frame = tkinter.Frame(page1_frame) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame, varname = "fig_width", vartype = 'int', defval = [config, 12], from_ = 1, to = 100, increment = 1, box_width = 6, reset_val = 12, # help_text = 'Width of graph window. Default: 12', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 4) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame, varname = "fig_height", vartype = 'int', defval = [config, 8], from_ = 1, to = 100, increment = 1, box_width = 6, reset_val = 8, # help_text = 'Hight of graph window. Default: 8', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 5) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame, varname = "fontsize", vartype = 'int', defval = [config, 16], from_ = 1, to = 100, increment = 1, box_width = 6, reset_val = 16, help_text = 'Size of graph font. Default: 16', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 6) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, graph_grid_frame, varname = "legend_fontsize", vartype = 'int', defval = [config, 8], from_ = 1, to = 100, increment = 1, box_width = 6, reset_val = 8, help_text = 'Size of legend font. Default: 8', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 7) return notebook_frame
[ドキュメント] def create_main_tab(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, parent_notebook: tkinter.ttk.Notebook) -> tkinter.Frame: """ 概要: メインの分析タブページを作成します。 詳細説明: 入力ファイル、出力ファイル、結果ファイル(npz)のパス設定、 分析・検証・引用・使用方法(CLI)ボタン、および各種計算パラメータ (グリッドサイズ、プローブ数、乱数シードなど)の入力ウィジェットを配置します。 メッセージボックスも含まれます。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param parent_notebook: tkinter.ttk.Notebook: 親となるノートブックウィジェット。 戻り値 (Returns): :returns: tkinter.Frame: 作成されたタブページフレーム。 """ config = app.configparams ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() page1_frame = tktkinter.Frame(app, parent_notebook, bg = 'dim gray') page1_frame.pack() parent_notebook.add(page1_frame, text = app.p('Analyze')) notebook_frame = page1_frame applications = app.get_external_apps(config.get("editor_path", None)) path_grid_frame = tkinter.Frame(page1_frame) # Parameter path frame """ tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, tkvars, varname = 'prmpath', file_type = [("Parameter", "*.prm"), ("All", "*.*")], working_dir = '.', is_print = True, igridrow = 0) """ # Input path frame def open_file(input_entry, output_entry, outres_entry, file_type = None, ini_dir = None): ini = tkIniFile(path = config.inifile) if ini_dir is None: ini_dir = ini.get_string(section = "work_dir", key = "last_dir", def_val = '.', is_print = False) tktkinter.path_button_click(app, input_entry, file_type = file_type, ini_dir = ini_dir) file_path = input_entry.get() outfile = app.replace_path(file_path, template = ["{dirname}", "{filebody}-predict{i}.xlsx"], ext_dict = {'i': '{i}'}) output_entry.set(outfile) cparams.outfile = outfile outresfile = app.replace_path(file_path, template = ["{dirname}", "{filebody}-save{i}.npz"], ext_dict = {'i': '{i}'}) outres_entry.set(outresfile) cparams.outresfile = outresfile ini.write_string(section = "work_dir", key = "last_dir", value = dir, is_print = False) tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, tkvars, varname = 'infile', file_type = [("Excel", "*.xlsx"), ("CSV", "*.csv"), ("All", "*.*")], working_dir = '.', head_label_width = config.head_label_width, entry_width = config.entry_width, button_width = config.head_label_width, edit_button_width = 0, shell_button_width = 0, open_command = lambda app, cparams, file_type, ini_dir: \ open_file(tkvars["infile"], tkvars["outfile"], tkvars["outresfile"], file_type, ini_dir = None), # post_open_command = lambda: post_open(tkvars["infile"], tkvars["outfile"]), is_print = True, igridrow = 1) # Output path frame tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, tkvars, varname = 'outfile', file_type = [("Excel", "*.xlsx"), ("All", "*.*")], working_dir = '.', head_label_width = config.head_label_width, entry_width = config.entry_width, button_width = config.button_width, edit_button_width = 0, shell_button_width = 0, is_print = True, igridrow = 2) # npz path frame tktkinter.make_path_frame(app, cparams, page1_frame, path_grid_frame, tkvars, varname = 'outresfile', file_type = [("npz", "*.npz"), ("All", "*.*")], working_dir = '.', head_label_width = config.head_label_width, entry_width = config.entry_width, button_width = config.button_width, edit_button_width = 0, shell_button_width = 0, is_print = True, igridrow = 3) # Button def analyze(app, cparams, tkvars): copy_tkvars(app, cparams, tkvars) print("") print("Execute analysis") c_engine.execute(app, cparams, wait_by_input = False) def validate(app, cparams, tkvars): copy_tkvars(app, cparams, tkvars) print("") print("Execute analysis") c_engine.validate(app, cparams, wait_by_input = False) def usage_cli(app, cparams, tkvars): copy_tkvars(app, cparams, tkvars) print("") # cparams.infile = tkvars['infile'].get() c_engine.usage(app) button_frame = tkinter.Frame(page1_frame) button1 = tktkinter.Button(app, button_frame, text = 'analyze', width = 8, font = ("", 16), command = lambda: analyze(app, cparams, tkvars)) button1.pack(side = tkinter.LEFT) button2 = tktkinter.Button(app, button_frame, text = 'validate', width = 8, font = ("", 16), command = lambda: validate(app, cparams, tkvars)) button2.pack(side = tkinter.LEFT) button3 = tktkinter.Button(app, button_frame, text = 'citation', width = 8, font = ("", 10), command = lambda: c_engine.citation(app)) button3.pack(side = tkinter.RIGHT) button4 = tktkinter.Button(app, button_frame, text = 'usage(cli)', width = 8, font = ("", 10), command = lambda: usage_cli(app, cparams, tkvars)) button4.pack(side = tkinter.RIGHT) button_frame.pack(side = tkinter.TOP, anchor = 'w', padx = 2, pady = 2, fill = tkinter.X, expand = True) # Parameter block vars_grid_frame = tkinter.Frame(page1_frame) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = 'nx_2D', vartype = 'int', defval = [config, 11], from_ = 1, to = 101, increment = 10, box_width = 6, reset_val = 11, # help_text = 'ma_num_probes', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 0) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = 'ny_2D', vartype = 'int', defval = [config, 11], from_ = 1, to = 100, increment = 10, box_width = 6, reset_val = 11, # help_text = 'ma_num_probes', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 1) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = 'max_num_probes', vartype = 'int', defval = [config, 1], from_ = 1, to = 100, increment = 5, box_width = 6, reset_val = 1, # help_text = 'ma_num_probes', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 2) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = 'num_search_each', vartype = 'int', defval = [config, 1], from_ = 1, to = 100, increment = 5, box_width = 6, reset_val = 1, # help_text = 'Number of probes at each iteration. Default: 0', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 3) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = "num_rand_basis", vartype = 'int', defval = [config, 200], from_ = 1, to = 5000, increment = 50, box_width = 6, reset_val = 200, # help_text = 'Number of random Gauss bases. Default: 200', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 4) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = "interval", vartype = 'int', defval = [config, 0], from_ = 1, to = 5000, increment = 10, box_width = 6, reset_val = 0, # help_text = 'Iterations to update hyper parameters. Default: 0', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 5) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = "score_mode", vartype = 'str', defval = [config, 'EI'], values = ['EI', 'PI', 'TS'], box_width = 6, reset_val = 'EI', # help_text = 'Type of aquisition function. Default: EI', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 6) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = "random_seed", vartype = 'str', defval = '', reset_val = '', # help_text = 'Seed for random numbers. Leave blank ("": null) to apply random seed. ' \ # + 'Specify an integer if you need reprodcible random numbers. Default: ""[null]', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 7) frame = tktkinter.make_var_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = "fraction_test", vartype = 'float', defval = 0.0, from_ = 0.0, to = 1.0, increment = 0.1, box_width = 6, reset_val = 0.0, # help_text = 'Fraction or number of test data. < 1.0 specifies fraction >= 1 specifies the number. Default: 0.0', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, igridrow = 8) frame = tktkinter.make_check_box(app, cparams, tkvars, page1_frame, vars_grid_frame, varname = "standardize", label = 'standardize', reset_val = 1, # help_text = 'Number of random Gauss bases. Default: 200', button1_args = {'text': 'default', "width": 6, 'font': ("", 10), 'command': 'set_default'}, button2_args = {'text': 'help', "width": 6, 'font': ("", 10), 'command': 'show_help'}, onvalue = 1, offvalue = 0, igridrow = 9) # Message text box textframe = tktkinter.Frame(app, page1_frame, bg = 'dim gray') message_box = tktkinter.Text(app, textframe, width = config.get("message_box_width", 100), height = config.get("message_box_height", 5)) scrollbar = tkinter.Scrollbar(textframe, orient = tkinter.VERTICAL, command = message_box.yview) message_box["yscrollcommand"] = scrollbar.set message_box.grid(row = 0, column = 0) scrollbar.grid(row = 0, column = 1, sticky = (tkinter.N, tkinter.S)) textframe.pack(side = tkinter.TOP, anchor = 'w', expand = True, padx = 2, pady = 2) tkvars['message_box'] = message_box return notebook_frame
[ドキュメント] def create_canvas_tab(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, pane: tkinter.ttk.Notebook, title: str) -> tkinter.Frame: """ 概要: Canvasウィジェットを含むタブページを作成します。 詳細説明: 指定されたペイン内に新しいフレームを作成し、その中にTkinterのCanvasウィジェットを配置します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param pane: tkinter.ttk.Notebook: 親となるノートブックウィジェット。 :param title: str: タブページのタイトル。 戻り値 (Returns): :returns: tkinter.Frame: 作成されたタブページフレーム。 """ title = app.p(title) frame = tktkinter.Frame(app, pane, bg='dim gray') pane.add(frame, text = title) app.canvas = tktkinter.Canvas(app, frame) return frame
[ドキュメント] def create_left_frame4(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, pane: tkinter.ttk.Notebook, title: str): """ 概要: Treeviewウィジェットを含むタブページ(左ペインのフレーム)を作成します。 詳細説明: 指定されたペイン内に新しいフレームを作成し、その中に階層的なデータを 表示するためのTreeviewウィジェットを配置します。 いくつかのサンプルデータが挿入されます。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param pane: tkinter.ttk.Notebook: 親となるノートブックウィジェット。 :param title: str: タブページのタイトル。 """ title = app.p(title) frame = tktkinter.Frame(app, pane, bg='dim gray') pane.add(frame, text = title) treeview = tkinter.ttk.Treeview(frame, columns=["colA", "colB", "colC"]) treeview.column("#0", width=100) treeview.column("colA", width=80) treeview.column("colB", width=80) treeview.column("colC", width=80) treeview.heading("#0", text="階層列") treeview.heading("colA", text="データ列A") treeview.heading("colB", text="データ列B") treeview.heading("colC", text="データ列C") itemAId = treeview.insert("", tkinter.END, text="itemA", open=True, values=("data1a", "data1b", "data1c")) itemBId = treeview.insert(itemAId, tkinter.END, text="itemB", open=True, values=("data2a", "data2b", "data2c")) itemCId = treeview.insert(itemBId, tkinter.END, text="itemC", values=("data3a", "data3b", "data3c")) itemDId = treeview.insert("", tkinter.END, text="itemD", values=("data4a", "data4b", "data4c")) treeview.pack()
[ドキュメント] def create_left_frame3(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, pane: tkinter.ttk.Notebook, title: str): """ 概要: TextウィジェットとListboxウィジェットを含むタブページ(左ペインのフレーム)を作成します。 詳細説明: 指定されたペイン内に新しいフレームを作成し、その中に複数行テキスト入力用の Textウィジェットと項目選択用のListboxウィジェットを配置します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param pane: tkinter.ttk.Notebook: 親となるノートブックウィジェット。 :param title: str: タブページのタイトル。 """ title = app.p(title) frame = tktkinter.Frame(app, pane, bg='dim gray') pane.add(frame, text = title) textframe = tktkinter.Frame(app, frame, bg='dim gray') textframe.pack() text = tkinter.Text(textframe, height = 4, width = 20) scrollbar = tkinter.Scrollbar(textframe, orient = tkinter.VERTICAL, command=text.yview) text["yscrollcommand"] = scrollbar.set text.grid(row=0, column=0) scrollbar.grid(row=0, column=1, sticky=(tkinter.N, tkinter.S)) listbox = tkinter.Listbox(frame) for month in ("1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"): listbox.insert(tkinter.END, month) listbox.pack() output_text = tktkinter.Text(app, frame, width = 60, height = 10) output_text.pack(side = tkinter.TOP, anchor = 'w', expand = True, padx = 2, pady = 2)
# tkvars['outputtext'] = output_text
[ドキュメント] def create_left_frame2(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams, pane: tkinter.ttk.Notebook, title: str) -> tkinter.Frame: """ 概要: 多様なTkinterウィジェットを含むタブページ(左ペインのフレーム)を作成します。 詳細説明: Menubutton、Scale、カスタムダイアログを起動するボタン、Progressbar、 Checkbutton、OptionMenu、Combobox、Radiobutton、Spinboxなど、 様々なTkinterウィジェットを配置します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 :param pane: tkinter.ttk.Notebook: 親となるノートブックウィジェット。 :param title: str: タブページのタイトル。 戻り値 (Returns): :returns: tkinter.Frame: 作成されたタブページフレーム。 """ title = app.p(title) frame = tktkinter.Frame(app, pane, bg='dim gray') pane.add(frame, text = title) mb = tkinter.Menubutton(frame, text="menubutton:Select alphabet") mb.pack() menu = tkinter.Menu(mb) menu.add_command(label="A") menu.add_command(label="B") mb["menu"] = menu scale = tkinter.Scale(frame, width = 20, length = 300, label = 'title', orient = tkinter.HORIZONTAL, showvalue = True, from_ = 0, to = 100, tickinterval = 20) scale.pack() class CustomDialog(tkinter.simpledialog.Dialog): """ 概要: カスタムダイアログボックスを実装するクラス。 詳細説明: `tkinter.simpledialog.Dialog` を継承し、独自のボディとボタンボックスを定義します。 引数 (Parameters): :param master: tkinter.Widget: 親ウィジェット。 :param title: str or None: ダイアログのタイトル。 """ def __init__(self, master: tkinter.Widget, title: str = None) -> None: """ 概要: CustomDialogクラスのコンストラクタ。 詳細説明: 親クラスのコンストラクタを呼び出し、ダイアログを初期化します。 引数 (Parameters): :param master: tkinter.Widget: 親ウィジェット。 :param title: str or None: ダイアログのタイトル。 """ super(CustomDialog, self).__init__(parent=master, title=title) def body(self, master: tkinter.Frame) -> None: """ 概要: ダイアログのメインコンテンツ領域を作成します。 詳細説明: エントリウィジェットを配置します。 引数 (Parameters): :param master: tkinter.Frame: ダイアログのボディフレーム。 """ entry = tkinter.Entry(master) entry.grid(column=0, row=0) def buttonbox(self): """ 概要: ダイアログの下部にあるボタン領域を作成します。 詳細説明: 「OK」ボタンと「Cancel」ボタンを配置し、それぞれのコマンドを割り当てます。 「OK」ボタンは初期状態で無効化されています。 """ box = tkinter.Frame(self) self.button1 = tkinter.Button(box, text="OK", width=10, command=self.ok, state=tkinter.DISABLED) self.button1.pack(side=tkinter.LEFT, padx=5, pady=5) self.button2 = tkinter.Button(box, text="Cancel", width=10, command=self.cancel) self.button2.pack(side=tkinter.LEFT, padx=5, pady=5) box.pack() def switchButtonState(self): """ 概要: 「OK」ボタンの状態を切り替えます。 詳細説明: 現在「OK」ボタンの状態が `DISABLED` であれば `NORMAL` に変更します。 注意: ここでは `tk.DISABLED` が使用されていますが、 このスコープでは `tk` は未定義の可能性があります。 """ if self.button1['state'] == tk.DISABLED: # Bug: tk is not defined. Should be tkinter.DISABLED self.button1['state'] = tk.NORMAL def apply(self): # ダイアログボックスを閉じた後 """ 概要: ダイアログが閉じられた後に実行される処理を定義します。 詳細説明: このメソッドは、ダイアログがOKボタンで閉じられた際に自動的に呼び出されますが、 現在はこのメソッドで具体的な処理は定義されていません。 """ pass # print(self.var.get()) def display_dialog(): CustomDialog(pane) # tkinter.simpledialog.Dialog(pane) button = tktkinter.Button(app, frame, text = "dialog", command = display_dialog) button.pack(side = 'top', anchor = 'w', padx = 5, pady = 5) progressbar = tkinter.ttk.Progressbar(frame, value = 50) progressbar.pack() check_var = tkinter.BooleanVar(value = True) # check_var.set(True) # イベントハンドラーでget()しないと正常に初期化されない def checked_button(): # print("checked", check_var.get()) check_var.get() check = tkinter.Checkbutton(frame, variable = check_var, text = '選択しますか?', onvalue = True, offvalue = False, command = checked_button) check.pack() var = tkinter.StringVar() var.set('aaa') optionmenu = tkinter.OptionMenu(frame, var, 'aaa', 'bbb') optionmenu.pack() combobox = tkinter.ttk.Combobox(frame, values=('aaa', 'bbb', 'ccc')) combobox.pack() rdvar = tkinter.StringVar() rdvar.set('B') aButton = tkinter.Radiobutton(frame, variable = rdvar, value = 'A', text = 'Option A') #, command = self.showValue) aButton.pack() bButton = tkinter.Radiobutton(frame, variable = rdvar, value = 'B', text = 'Option B') #, command=self.showValue) bButton.pack() spinbox = tkinter.Spinbox(frame, cursor = 'clock', from_ = 0, to = 100, increment = 3, format = '%12.6f') spinbox.pack() return frame
[ドキュメント] def create_window(app: tkApplication_GUI, config: tkIniFile, cparams: tkParams): """ 概要: GUIアプリケーションのメインウィンドウとタブページを作成します。 詳細説明: メインウィンドウを初期化し、ツールバーと、メイン分析、グラフ設定、開発、 エディタ、様々なウィジェットのテスト用のタブページを含むノートブックペインを配置します。 引数 (Parameters): :param app: tkApplication_GUI: GUIアプリケーションのメインインスタンス。 :param config: tkIniFile: 設定パラメータを管理するオブジェクト。 :param cparams: tkParams: 計算エンジン用パラメータを管理するオブジェクト。 """ ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() root_window = app.create_window(title = sys.argv[0], geometry = config.geometry, minsize = config.minsize) # menu_bar = create_menu(app, config, cparams, root_window) tool_bar = create_toolbar(app, config, cparams, root_window) # 2分割ウインドウを使う場合。いづれのpaneもnotebook型ウインドウが作られる # panes = app.add_root_panes(root = root_window, type = "pane2", sashwidth = 2, left_pane_width = 600) # main_pane, left_notebook, right_notebook = panes # 1分割ウインドウを使う場合。paneはnotebook型ウインドウが作られる panes = app.add_root_panes(type = "pane1", sashwidth = 2) left_notebook = panes[0] # 左ペインのnotebookにタブを追加 ltabframe1 = create_main_tab(app, config, cparams, left_notebook) ltabframe2 = create_graph_tab(app, config, cparams, left_notebook) ltabframe3 = app.create_development_tab(config, cparams, left_notebook, copy_tkvars = copy_tkvars) ltabframe4 = app.create_editor_tab(config, cparams, left_notebook, title = 'Editor test', entry_width = 35, eval_button_args = { 'text': 'eval', 'width': 4, "command": None }, ) # ltabframe6 = create_canvas_tab(app, config, cparams, left_notebook, title = 'Canvas test') ltabframe6 = create_left_frame2(app, config, cparams, left_notebook, title = 'Widget test1') ltabframe7 = create_left_frame3(app, config, cparams, left_notebook, title = 'Widget test2') ltabframe8 = create_left_frame4(app, config, cparams, left_notebook, title = 'Widget test3') app.mainloop()
[ドキュメント] def main(): """ 概要: アプリケーションのエントリーポイント。 詳細説明: `tkApplication_GUI` のインスタンスを初期化し、設定ファイルからパラメータを読み込み、 コマンドライン引数で更新し、GUIウィンドウを作成して表示します。 終了時には設定をiniファイルに保存します。 """ #================================================================== # Initialize parameters #================================================================== app = tkApplication_GUI(usage_str = usage_str, globals = globals(), locals = locals(), use_user_inifile = True, inifile_dirs = ['../../user', 'user'], create_inidir = False) app.env = os.environ # 設定パラメータオブジェクト config = app.configparams cparams = app.get_params() # 計算エンジンのパラメータオブジェクト ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() mtime = time.localtime(os.path.getctime(app.script_path)) print("") print( "################################################") print(f"# {app.script_path} ver {version[0]}.{version[1]}.{version[2]}") print(f"# Modified time: {mtime.tm_year}/{mtime.tm_mon}/{mtime.tm_mday} {mtime.tm_hour}:{mtime.tm_min}:{mtime.tm_sec}") print( "################################################") print(f"Initialize parameters") initialize(app, config) # 本GUIの設定パラメータオブジェクト config = app.configparams # GUIウィジェット変数オブジェクトと辞書型 ctkvars = app.tkvars tkvars = ctkvars.get_param_dict() print(f"Read configration from [{config.inifile}]") config.read_parameters(path = config.inifile) print(f"Update parameters by command-line arguments") update_vars(app, cparams) app.resource_path = os.path.join(app.resource_dir, f'resource_{app.config.lang}.resource') app.phrases = app.read_resource(app.resource_path, app.config.lang) #, app.phrases) work_dir = None infile = config.get('infile', None) if infile is not None: work_dir, basename, filebody, ext = split_file_path(infile) if work_dir is None: work_dir = config.get('work_dir', None) if work_dir is not None and work_dir != '': if os.path.exists(work_dir): os.chdir(work_dir) create_window(app, config, cparams) infile = config.get('infile', None) if infile is not None: work_dir, basename, filebody, ext = split_file_path(infile) if work_dir is not None: config.work_dir = work_dir # ウィジェットの設定tkvarsをcparams,confgにコピー copy_tkvars(app, cparams, tkvars) copy_tkvars(app, config, tkvars) # <-- この行は `copy_tkvars(app, config, tkvars)` と解釈される。 # 第一引数がapp、第二引数がcparamsまたはconfig、第三引数がtkvarsと期待されるため、 # configオブジェクトに対してtkvarsから設定値をコピーする処理として解釈される。 # メインウインドウサイズをconfigにコピー config.geometry = app.root_window_geometry print("") print(f"Save configuration to [{config.inifile}]") config.save_parameters(path = config.inifile, section = 'Configure', sort_by_keys = True, IsPrint = False) # 必要があれば、入力ファイルに対応するパラメータファイルを保存 if tkvars.get("prmpath", None) is not None: cparams.prmpath = tkvars["prmpath"].get() #os.path.splitext(cparams.path)[0] + '.prm' if cparams.prmpath != '': print(f"Save parameters to [{cparams.prmpath}]") ret = cparams.save_parameters(cparams.prmpath, section = 'Parameters', sort_by_keys = True, IsPrint = False, update_commandline = False) if not ret: app.terminate(f"Error in main(): Cannot write to [{cparams.prmpath}]", usage = usage) app.terminate()
if __name__ == "__main__": main()