2016-09-18 342 views
3

私はこのプログラムを停止するまで毎秒ビープ音を鳴らします。問題は、「開始」を押してビープ音が鳴った後、ウィンドウがフリーズして「停止」ボタンをクリックできなくなることです。どんな助けも歓迎です。TKinter - 停止ボタンでループを止めるには?

#!/usr/bin/python 
import Tkinter, tkMessageBox, time, winsound, msvcrt 

running = True 

Freq = 2500 
Dur = 150 

top = Tkinter.Tk() 
top.title('MapAwareness') 
top.geometry('200x100') # Size 200, 200 

def start(): 
    sec = 0 
    while running: 
     if sec % 1 == 0: 
      winsound.Beep(Freq, Dur) 

     time.sleep(1) 
     sec += 1 

def stop(): 
    running = False 

startButton = Tkinter.Button(top, height=2, width=20, text ="Start", command = start) 
stopButton = Tkinter.Button(top, height=2, width=20, text ="Stop", command = stop) 

startButton.pack() 
stopButton.pack() 

top.mainloop() 
+0

あなただけのランニングんが場合:それはただそれだけのどちらか、稼働を維持if文、whileループ内で追加したり、実行中のようなものを行いますので、実行しているが偽の間、として実行されます==真。 – Elxafil

答えて

3

コードにはいくつか問題があります。まず、time.sleep()は、mainloop()と干渉するため、Tkinterプログラムで使用しないでください。代わりに、一般的にユニバーサルウィジェットのメソッド.after()を使用して、指定された遅延後に関数を実行するようにスケジュールします。

グローバル変数を正しく使用していません。ある関数内の名前付き変数に値を代入すると、前にその名前が宣言されていない限り、ローカル変数が作成されますglobal。たとえば、stop()関数は、runningという名前のローカル変数を作成し、その値を0に設定すると、ではなく、は同じ名前のグローバル変数の値を変更します。

前の規則は、変数の現在の値を参照(読み取り)するだけには適用されません。そのため、FreqDurのグローバルをstart()に宣言していないのは問題ありません。

もう1つの問題は、start()機能のsec % 1 == 0です。 % 1の値は0です。奇数/偶数をチェックするにはsec % 2を使用します。

PEP 8 - Style Guide for Python Codeに従うように再フォーマットされた作業用バージョンです。

import Tkinter 
import tkMessageBox 
import time 
import winsound 

FREQ = 2500 
DUR = 150 

after_id = None 
secs = 0 

def beeper(): 
    global after_id 
    global secs 
    secs += 1 
    if secs % 2 == 0: # every other second 
     winsound.Beep(FREQ, DUR) 
    after_id = top.after(1000, beeper) # check again in 1 second 

def start(): 
    global secs 
    secs = 0 
    beeper() # start repeated checking 

def stop(): 
    global after_id 
    if after_id: 
     top.after_cancel(after_id) 
     after_id = None 

top = Tkinter.Tk() 
top.title('MapAwareness') 
top.geometry('200x100') 

startButton = Tkinter.Button(top, height=2, width=20, text="Start", 
          command=start) 
stopButton = Tkinter.Button(top, height=2, width=20, text="Stop", 
          command=stop) 
startButton.pack() 
stopButton.pack() 
top.mainloop() 
+0

それは完全に働いた。どうもありがとう! –

1

問題は、start()ブロックGUIハンドラmainloop()でwhileループ。 start()Tk.after()を使用してみてください:

def start(force=True): 
    global running 
    if force: 
     running = True 
    if running: 
     winsound.Beep(Freq, Dur) 
     top.after(1000, start, False) 

そしてstop()を変更:

def stop(): 
    global running 
    running = False 
2

あなたのコードその内部で実行されているwhileループを持っており、その上に、あなたもdef start():内部のwhileループを持っているtop.mainloop()を持っています。ループ内のループのようなものです。

ループの本体に必要な機能を作成することができます。これは、ループの繰り返しを1回だけ行う必要があります。それが完了したら、それは、afterを使用して、それ自身が将来何度か呼び出されるように手配する必要があります。どのくらい前から、あなたのループがどのくらい速く走るかが決まります。

そして、after_cancelを使用してイベントを取り消すことができます。以下のコードは私のために働いた

import Tkinter, tkMessageBox, time, winsound, msvcrt 

Freq = 2500 
Dur = 150 

top = tkinter.Tk() 
top.title('MapAwareness') 
top.geometry('200x100') # Size 200, 200 

def start(): 
    global job1 
    if running == True: 
     winsound.Beep(Freq, Dur) 
     job1 = top.after(1000, start) # reschedule event in 1 seconds 

def stop(): 
    global job1 
    top.after_cancel(job1) 

startButton = tkinter.Button(top, height=2, width=20, text ="Start", command = start) 
stopButton = tkinter.Button(top, height=2, width=20, text ="Stop", command = stop) 

startButton.pack() 
stopButton.pack() 
#top.after(1000, start) 
top.mainloop() 
+0

OPの既存コードの説明と修正。 – martineau

1

もう一度パンチに殴られるが、ここには何もない。上記のように、mainloopのブロックを防ぐには、after関数を使用します。
参照: tkinter: how to use after method

#!/usr/bin/python 
import Tkinter, tkMessageBox, time 

Freq = 2500 
Dur = 150 

top = Tkinter.Tk() 
top.title('MapAwareness') 
top.geometry('200x100') # Size 200, 200 

def start(): 
    print ("Beep") 
    top.after(1000, start) 

def stop(): 
    print ("Stop") 
    top.quit() 

startButton = Tkinter.Button(top, height=2, width=20, text ="Start", command = start) 
stopButton = Tkinter.Button(top, height=2, width=20, text ="Stop", command = stop) 

startButton.pack() 
stopButton.pack() 
top.mainloop() 
関連する問題