前提・実現したいこと
初めてPythonのtkinterを利用してツール作成を行っています。
やりたいこととしては、テキストボックスにパスを入力し、ボタンを押下すると
オプションメニューの値が更新される処理を実現したいです。
発生している問題・エラーメッセージ
どのようにしてオプションメニューの値を更新すればいいでしょうか。 当然ですが、このまま実行しても変数に値が入るだけで更新はされません。 オプションメニューのインスタンス化する場所を変更する? 詰まっているためご教授頂けると嬉しいです。
該当のソースコード
python
1import sys 2import abc 3import re 4from copy import copy 5import tkinter as tk 6 7#test path 8test_path = 'xxx' 9file_contents = [] 10#---------------------------------------- 11 12class TKroot(tk.Tk): 13 def __init__(self): 14 super().__init__() 15 self.title('xxx') 16 self.geometry('1000x600') 17 self.config(bg = 'white') 18 19 20class Application(tk.Frame): 21 file_mode = 'r' 22 23 def __init__(self, master = None, **kwargs): 24 super().__init__(master, **kwargs) 25 self.opt_value = {} 26 self.entry_value = {} 27 self.create_widget() 28 self.pack() 29 30 def create_widget(self): 31 global file_contents 32 33 #create frame 1. 34 self.f1 = tk.Frame(self, bg = 'coral') 35 self.f1.place(relheight = 0.1, width = 1000, height = 10) 36 self.f1_label = tk.Label(self.f1, text = 'path : ') 37 self.f1_label.pack(side = tk.LEFT) 38 var = tk.StringVar() 39 self.f1_entry = tk.Entry(self.f1, width = 100, textvariable = var) 40 self.f1_entry.pack(side = tk.LEFT) 41 42 f1_file = self.file_new() 43 self.f1_button = tk.Button(self.f1, text = 'update', width = 30, command = lambda : f1_file.control(Read, var)) 44 self.f1_button.pack(side = tk.RIGHT, padx = 40) 45 46 #create frame 2. 47 self.f2 = tk.Frame(self, bg = 'red') 48 self.f2.place(width = 1000, y = 70) 49 self.f2_label = tk.Label(self.f2, text = 'function name : ') 50 self.f2_label.pack(side = tk.LEFT) 51 self.f2_opt_variable = tk.StringVar() 52 #self.f2_opt_variable.set('chose a function') 53 if file_contents == []: 54 file_contents.append("test") 55 file_contents.append("test") 56 self.f2_opt_variable.set(file_contents[0]) 57 self.f2_file_contents = copy(file_contents) 58 self.f2_opt = tk.OptionMenu(self.f2, self.f2_opt_variable, *self.f2_file_contents) 59 self.f2_opt.config(width = 80) 60 self.f2_opt.pack(side = tk.LEFT) 61 62 def file_new(self): 63 return File(Application.file_mode) 64 65 66class File: 67 def __init__(self, file_mode): 68 self._file_path = '' 69 self._file_mode = file_mode 70 71 def _get_items(self, file_type): 72 file_types_read = file_type(self._file_path, self._file_mode) 73 return file_types_read.lines() 74 75 def _set_items(self, function_list): 76 global file_contents 77 file_contents = [s for s in function_list if re.match(r'xxx', s)] 78 79 def control(self, file_type, path_object): 80 self._file_path = self._get_filepath(path_object) 81 self._set_items(self._get_items(file_type)) 82 83 def _get_filepath(self, path_object): 84 return path_object.get() 85 86class FileType(abc.ABC): 87 @abc.abstractclassmethod 88 def lines(self, file_path): 89 pass 90 91#------------------------------------途中------------------------------------- 92class Write(FileType): 93 def __init__(self, args : dict): 94 self._file_path = args.get('file_path', test_path) 95 self._file_mode = args.get('file_mode', 'w') 96 self._file_contens = [] 97 98 def lines(self): 99 with FileAccess(self._file_path) as file: 100 self._file_contens = file._writelines() 101 return self._file_contens 102#----------------------------------------------------------------------------- 103class Read(FileType): 104 def __init__(self, args_1, args_2): 105 self._file_path = args_1 106 self._file_mode = args_2 107 self._file_contens = [] 108 109 def lines(self): 110 with FileAccess(self._file_path) as file: 111 self._file_contens = file._readlines() 112 return self._file_contens 113 114 115class FileAccess(object): 116 def __init__(self, file_path): 117 self._file_path = file_path 118 self._file = None 119 120 def _open(self): 121 self._file = open(self._file_path) 122 #self._file = open(test_path) 123 124 def _close(self): 125 self._file.close() 126 127 def __enter__(self): 128 self._open() 129 return self 130 131 def __exit__(self, exc_type, exc_value, traceback): 132 self._close() 133 134 def _readlines(self): 135 file_read_contens = self._file.readlines() 136 return file_read_contens 137 138 def _writelines(self): 139 file_write_contens = self._file.writelines() 140 return file_write_contens 141 142def main(): 143 root = TKroot() 144 app = Application(master = root, width = 1000, height = 600) 145 app.mainloop() 146 147if __name__ == "__main__": 148 main()
試したこと
ここに問題に対して試したことを記載してください。
補足情報(FW/ツールのバージョンなど)
ここにより詳細な情報を記載してください。
>ボタンを押下すると
Update ボタンを押すとNameError: name 'Read' is not definedとでるので、
肝心な部分が省略されてます。
----
方向性としては、f2_opt_variable を引数として渡すか、
イベントで呼び出す関数をApplicationメソッドにして、
インスタンス経由でアクセスのどちらかになると思います。
teamikl様
ご回答ありがとうございます。省略部分を追記しました。
>>>方向性としては、f2_opt_variable を引数として渡すか、
f2_opt_variableを引数として渡す方法を行ってみましたが、オプションメニューの初期値が変更されるだけでデータとなる中身は更新されていませんでした。
>>>イベントで呼び出す関数をApplicationメソッドにして、
>>>インスタンス経由でアクセスのどちらかになると思います。
これは実施していないため憶測で記載し申し訳ありませんが、これも結局は引数で渡さないだけで、上の結果と同じようなことになると思われますがどうでしょうか。
すみません、初心者でいろいろ質問してしまいまして。。。
> 変数に値が入るだけで更新はされません。
「更新」とは具体的にどんな状態ですか?
>「オプションメニューの値」
オプションメニュー自体は選択された値を持っていなくて、
変数に指定するのは、表示されているラベルの様です。
選択された値が必要な場合は、コンボボックスの方が適してます。
OptionMenuを項目選択としてつかうには、可能ですが、
項目毎にイベントハンドラを設定する必要があります。
----
一応、f2_opt_variable (StringVar) のかわりに
f2_opt (OptionMenu)を渡すと、他にも色々出来ます。
回答にサンプルで項目を追加する例を記述しました。
>>>「更新」とは具体的にどんな状態ですか?
オプションメニューの内部データを更新することです。
回答の返信に結果を記載しました。
>>>選択された値が必要な場合は、コンボボックスの方が適してます。
わざわざイベントハンドラを設定しなくとも、textvariableで手軽に取得できますね。
今回はteamikl様がサンプルを記載くださったため、そちらを利用して実装することにします。
いろいろ答えていただきありがとうございました。本当に助かりました。
回答2件
あなたの回答
tips
プレビュー