2017-11-15 8 views
3

GUIとしてTkinterを使ってPythonでいくつかのドライブをプログラミングしています。私のマシンが動いているとき、私は、関数が完了した後でそれ自身を閉じるべきであるいくつかの情報を持つトップレベルのウィンドウをユーザに見せたいと思う。これは私の最小の例です:Python Tkinter、関数の後にトップレベルを破棄する

from Tkinter import * 
import time 


def button_1(): 
    window = Toplevel() 
    window.title("info") 
    msg = Message(window, text='running...', width=200) 
    msg.pack()  
    time.sleep(5.0) 
    window.destroy() 

master = Tk() 
frame = Frame(width=500,height=300) 
frame.grid() 
button_one = Button(frame, text ="Button 1", command = button_1) 
button_one.grid(row = 0, column = 0, sticky = W + E) 
mainloop() 

主な問題は、5秒後にトップレベルのウィンドウが表示されることです。助言がありますか? ありがとう!

+0

なぜあなたのコードはあなたが望んでいないと思いますか?これは、関数が完了した後に「それ自身」を閉じるか、あるいは閉じて関数を完了させます。 – Nae

答えて

2

time.sleep(5)がGUIの更新に先立って起動するため、トップレベルが5秒後に表示されるのはそのためです。これを修正するには、time.sleep(5)の前にwindow.update_idletasks()を追加して強制的に表示を更新します。

しかし、Bryan Oakleyが答えて指摘したように、GUIはフリーズしている間にtime.sleep(5)が実行されます。あなたの究極の目標はtime.sleepを実行するのではなく、いくらかの時間を要する操作だと思います。だから、あなたは、GUIを凍結したくない場合がありますが、分離のスレッドで、あなたの関数を実行し、それがafterを使用して終了したかどうかを定期的にチェックすることができ、実行がかかりますどのくらいかわからない:

import Tkinter as tk 
import time 
import multiprocessing 

def function(): 
    time.sleep(5) 


def button_1(): 
    window = tk.Toplevel(master) 
    window.title("info") 
    msg = tk.Message(window, text='running...', width=200) 
    msg.pack() 
    thread = multiprocessing.Process(target=function) 
    thread.start() 
    window.after(1000, check_if_running, thread, window) 


def check_if_running(thread, window): 
    """Check every second if the function is finished.""" 
    if thread.is_alive(): 
     window.after(1000, check_if_running, thread, window) 
    else: 
     window.destroy() 


master = tk.Tk() 
frame = tk.Frame(width=500,height=300) 
frame.grid() 
button_one = tk.Button(frame, text ="Launch", command=button_1) 
button_one.grid(row = 0, column = 0, sticky = "we") 
master.mainloop() 
1

A一般的なGUIが実行されているスレッドでsleepを決して呼び出すべきではないということです。その理由は、sleepはそれが言うことを正確に実行し、プログラム全体をスリープ状態にします。つまり、ウィンドウをリフレッシュすることも、何らかのイベントに反応することもできません。

一定期間後に何かしたい場合は、正しい方法はafterです。たとえば、これで5秒後にウィンドウが破棄されます。

window.after(5000, window.destroy) 
+0

答えをありがとう。これはほんの少しの例ですが、私は実際のプログラムで睡眠を呼びません。私ははるかに複雑な機能を呼んでいます。 – JohannesB

関連する問題