Python3.6.5 & Tkinter でのモーダルダイアログについての質問
PythonでGUIのタイマーアプリを作っています。
現在、カウントダウンが終了した際にその旨を最前面のウィンドウに通知する機能を実装しています。
手段として、モーダルダイアログを表示する方法をとりました。
その際、以下のエラーメッセージが発生しました。
※90行目あたり。コメントアウトした線で囲っている部分が !toplevel の該当部かと思われます。
発生している問題・エラーメッセージ
tkinter.TclError: bad window path name ".!toplevel"
該当のソースコード
Python
1# coding: utf-8 2 3import tkinter as tk 4from tkinter import messagebox 5import time 6#import winsound 7 8class Timer(tk.Frame): 9 WID = 10 10 countPushStartButton = 0 11 presetTime = 45 12 13 def __init__(self,master = None): 14 tk.Frame.__init__(self,master) 15 16 self.master.title('集中力タイマー') 17 18 #単位表記 19 minute = tk.Label(self, text = u'分',font = 'Arial, 12', padx = 5, pady = 5) 20 second = tk.Label(self, text = u'秒',font = 'Arial, 12', padx = 5, pady = 5) 21 22 #スピンボックス 23 self.minuteSpinbox = tk.Spinbox(self, value = Timer.presetTime, from_ = 0, to = 99, increment = 1, width = Timer.WID) 24 self.secondSpinbox = tk.Spinbox(self, from_ = 0, to = 59, increment = 1, width = Timer.WID) 25 26 #残り時間表示 27 self.countDownView = tk.Label(self,text = u'00:00',font = 'Arial, 25') 28 29 #押ボタン 30 self.startButton = tk.Button(self,text = 'Start',command = self.start) 31 resetButton = tk.Button(self,text = 'Reset', command = self.reset) 32 33 #ウィジェット配置 34 self.minuteSpinbox.grid(row = 0, column = 0, padx = 5, pady = 2) 35 minute.grid(row = 0, column =1, padx =5, pady = 2, sticky = tk.W) 36 self.secondSpinbox.grid(row = 0, column = 2, padx = 5, pady = 2) 37 second.grid(row = 0, column = 3, padx = 5, pady = 2, sticky = tk.W) 38 self.startButton.grid(row =1,column = 0, columnspan = 4,padx = 5, pady = 2, sticky = tk.W + tk.E) 39 resetButton.grid(row =2, column = 0, columnspan = 4,padx =5, pady = 2, sticky = tk.W + tk.E) 40 41 self.countDownView.grid(row = 3, column = 0, columnspan = 4, padx = 5, pady = 2, sticky = tk.W + tk.E) 42 43 #startボタン押下時動作 44 def start(self): 45 self.getSpinboxValue() 46 self.controlStartButton() 47 self.count() 48 49 #resetボタン押下時動作 50 def reset(self): 51 self.startButton.config(text = 'Start') 52 self.countDownView.config(text = '00:00') 53 Timer.countPushStartButton = 0 54 55 #Startボタンを押した回数によって動作を変える(初回「Start」、奇数「Stop」、偶数「Restart」) 56 def controlStartButton(self): 57 if Timer.countPushStartButton == 0: 58 self.finishTime = time.time() + self.secondsValue 59 self.isStarted = True 60 elif Timer.countPushStartButton % 2 == 0: 61 self.isStarted = True 62 else: 63 self.isStarted = False 64 Timer.countPushStartButton = Timer.countPushStartButton + 1 65 self.refreshStartButton() 66 67 #Startボタン押下回数によってボタン表示を変える 68 def refreshStartButton(self): 69 if self.isStarted is True: 70 self.startButton.config(text = 'Stop') 71 else: 72 self.startButton.config(text = 'Restart') 73 74 #カウントダウン機能 75 def count(self): 76 if self.isStarted: 77 self.remainingTime = self.finishTime - time.time() 78 if self.remainingTime < 0: 79 self.countDownView.config(text = "時間です") 80 self.openModalDialogOfNotifyingTimeOut() 81 #messagebox.showinfo('お知らせ','時間です') 82 #アラーム音を鳴らす 83 #winsound.PlaySound("SystemAsterisk",winsound.SND_ALIAS) 84 85 else: 86 self.countDownView.config(text = '%02d:%02d'%(self.remainingTime/60,self.remainingTime%60)) 87 #0.1秒後に関数countを呼び出す 88 self.after(100, self.count) 89 90 91#------------------------------------------------------------------------------------- 92 93 def openModalDialogOfNotifyingTimeOut(self): 94 self.modalDialogOfNotifyingTimeOut = tk.Toplevel() 95 self.modalDialogOfNotifyingTimeOut.title("時間です") 96 self.modalDialogOfNotifyingTimeOut.geometry("300x300") 97 self.modalDialogOfNotifyingTimeOut.grab_set() 98 99 closeButton = tk.Button(self.modalDialogOfNotifyingTimeOut, text ="閉じる", command = self.modalDialogOfNotifyingTimeOut.destroy()) 100 closeButton.pack() 101 102#-------------------------------------------------------------------------------------- 103 104 #単位変換 105 def getSpinboxValue(self): 106 minuteSpinboxValue = self.minuteSpinbox.get() 107 secondSpinboxValue = self.secondSpinbox.get() 108 c1 = int(minuteSpinboxValue) 109 c2 = int(secondSpinboxValue) 110 self.secondsValue = c1 * 60 + c2 111 112if __name__ == '__main__': 113 f = Timer() 114 f.pack() 115 f.mainloop() 116
試したこと
self.modalDialogOfNotifyingTimeOut.grab_set()
のあとに
self.modalDialogOfNotifyingTimeOut.pack()
を追加したところ、モーダルダイアログは表示されるようになりましたが、
AttributeError: 'Toplevel' object has no attribute 'pack'
というエラーが出るようになりました。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/04/01 23:55