少し前に、
Python3 Tkinter ダイアログ表示したい
にてダイアログを表示し、そこで選んだボタンの文字列(OK, キャンセルなど)やTrue, Falseを戻り値として取得したいという質問をしました。
そこで
teamikl様にsimpledialog.SimpleDialog をカスタマイズして使う提案をしていただいたのですが、以下のようにソースコードを書き換えたところ、RuntimeErrorが発生してしまいました。
スレッドを使っていない時は問題なく動作したので、スレッドの使い方やスレッドとの相性だと思うのですが、具体的な理由がわかりません。
対処方法を教えていただきたいです。
アプリケーションの仕様としては、ボタンを押した時にエントリが空だったらダイアログを表示する。ダイアログの続行ボタンを押した場合はエントリがから出なかった時と同じ処理(App.func())を実行、キャンセルを押した時は何もしない(returnする)ような感じです。
- main.py
Python
1import tkinter as tk 2import tkinter.ttk as ttk 3import threading 4import time 5from datetime import datetime 6 7import mydialog 8 9class App: 10 def __init__(self, win): 11 self.flag = True 12 self.win = win 13 self.create() 14 15 def create(self): 16 self.clock = tk.Label(self.win) 17 self.clock.grid() 18 self.entry = ttk.Entry(win) 19 self.entry.grid() 20 self.button = ttk.Button(win, text="click") 21 self.button.grid() 22 self.thread = threading.Thread(target=self.update) 23 self.thread.start() 24 self.bind_event() 25 26 def update(self): 27 while self.flag: 28 self.clock["text"] = datetime.now().strftime("%Y/%m/%d %H:%M:%S.%f") 29 time.sleep(0.001) 30 31 def bind_event(self): 32 self.button.bind("<ButtonRelease>", self.pushed) 33 34 def pushed(self, ev): 35 self.str = self.entry.get() 36 print("str:" + self.str) 37 if self.str == "": 38 ret = mydialog.askyesno(message="no str...", buttons=["続行", "キャンセル"], parent=self.win) 39 print(ret) 40 if ret == "続行": 41 pass 42 else: 43 return 44 self.func() 45 46 def func(self): 47 # 続行処理 48 pass 49 50 51def close(app): 52 app.flag = False 53 app.win.destroy() 54 55if __name__ == "__main__": 56 win = tk.Tk() 57 app = App(win) 58 win.protocol("WM_DELETE_WINDOW", lambda:close(app)) 59 win.mainloop()
- mydialog.py
Python
1import tkinter as tk 2from tkinter import ttk, simpledialog 3from functools import partial 4 5# https://teratail.com/questions/274362 6# 押されたボタンの文字列を戻り値とする 7 8def askyesno(title="", message="", buttons=["OK", "Cancel"], parent=None): 9 # messageのフォント変更 10 parent.option_add("*Message.font", "MSPゴシック 50") 11 # ボタンのフォント変更 12 font = ("", 20) 13 style = ttk.Style() 14 style.configure("MyDialog.TLabel", font=font) 15 style.configure("MyDialog.TButton", font=font) 16 simpledialog.Frame = partial(ttk.Frame, style="MyDialog.TFrame") 17 simpledialog.Label = partial(ttk.Label, style="MyDialog.TLabel") 18 simpledialog.Button = partial(ttk.Button, style="MyDialog.TButton") 19 dialog = simpledialog.SimpleDialog( 20 master=parent, 21 title=title, 22 text=message, 23 buttons=buttons 24 ) 25 return buttons[dialog.go()]
- 実行結果(続行ボタンを押した時のものだが、キャンセルボタンも同様のエラー).
str: 続行 Exception in thread Thread-1: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 932, in _bootstrap_inner self.run() File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/threading.py", line 870, in run self._target(*self._args, **self._kwargs) File "/Users/USER/Desktop/main.py", line 28, in update self.clock["text"] = datetime.now().strftime("%Y/%m/%d %H:%M:%S.%f") File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/tkinter/__init__.py", line 1648, in __setitem__ self.configure({key: value}) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/tkinter/__init__.py", line 1637, in configure return self._configure('configure', cnf, kw) File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/tkinter/__init__.py", line 1627, in _configure self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) RuntimeError: main thread is not in main loop
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。