Tkinterで次のようなアプリを作りたいです。
ボタンを押すと、エントリの文字列をCSVに書き込む。
ただし書き込み中は、画面の操作を不可能(state -> disable)にする。
書き込みが終わったら、画面の操作を可能(state -> normal)にする。
(仕様について、なぜ画面の操作を不可能にするかなどは気にしないでください。)
ソースコードを下記のように作りましたが、一つ気になることがあります。
メインスレッド->サブスレッドはサブスレッドで都度キューのデータの取得をすればいいらしいですが、
サブスレッド->メインスレッドの場合はafter()を使えばいいのでしょうか?
(サブスレッドの処理のタイミングでUIを操作するため、コマンドとしてキューでメッセージを渡す。)
Python
1import csv 2import os 3import queue 4import sys 5import threading 6import time 7import tkinter as tk 8from datetime import datetime 9from tkinter import messagebox 10 11 12def on_thread1(): 13 global loop_flag, from_main_to_sub, from_sub_to_main 14 15 while loop_flag: 16 while not from_main_to_sub.empty(): 17 data = from_main_to_sub.get_nowait() 18 if data[0] == "WRITE_CSV": 19 from_sub_to_main.put("STATE_DISABLED") 20 time.sleep(1) # UI無効確認用 21 txt = data[1] 22 write_csv(txt) 23 from_sub_to_main.put("STATE_NORMAL") 24 25 26def write_csv(txt): 27 dir_ = os.path.abspath(os.path.dirname(sys.argv[0])) 28 fle = os.path.join(dir_, "test.csv") 29 30 with open(fle, "a", encoding="utf_8", newline="") as wf: 31 writer = csv.writer(wf) 32 writer.writerow([datetime.now(), txt]) 33 34 35def on_after(): 36 global from_sub_to_main 37 38 while not from_sub_to_main.empty(): 39 data = from_sub_to_main.get_nowait() 40 if data == "STATE_DISABLED": 41 entry.configure(state = "disabled") 42 button.configure(state = "disabled") 43 elif data == "STATE_NORMAL": 44 entry.configure(state = "normal") 45 button.configure(state = "normal") 46 entry.delete(0, "end") 47 else: 48 pass 49 50 root.after(100, on_after) 51 52 53def on_button(): 54 global from_main_to_sub 55 56 txt = entry.get() 57 if txt: 58 from_main_to_sub.put(["WRITE_CSV", txt]) 59 else: 60 messagebox.showerror("Error", "Please enter.") 61 62 63def on_close(): 64 global loop_flag, thread1 65 66 loop_flag = False 67 thread1.join() 68 root.destroy() 69 70 71loop_flag = True 72from_main_to_sub = queue.Queue() 73from_sub_to_main = queue.Queue() 74 75thread1 = threading.Thread(target=on_thread1) 76thread1.start() 77 78root = tk.Tk() 79root.geometry("300x200") 80root.protocol("WM_DELETE_WINDOW", on_close) 81 82entry = tk.Entry(root) 83entry.grid() 84 85button = tk.Button(root, text="Button", width=10, command=on_button) 86button.grid() 87 88root.after_idle(on_after) 89 90root.mainloop()
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/24 15:59
2021/08/25 02:15
2021/08/25 12:45