2016-09-18 7 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()에 신고하지 않은 것이 문제가 아닙니다.

또 다른 문제는 start() 기능의 sec % 1 == 0입니다. % 1의 값은 0입니다. odd/evenness를 확인하려면 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

당신의 코드가 그 안에 당신은 또한 def start(): 내부 while 루프를 가지고 그 꼭대기에서 실행되는 while 루프를 가지고 top.mainloop() 있습니다. 그래서 그것은 내부 루프 루프와 같습니다.

루프 본문에 원하는 기능을 만들 수 있습니다. 루프의 반복을 정확히 수행해야합니다. 완료되면을 사용하여 나중에 다시 호출 할 수 있도록 준비해야합니다. 앞으로 얼마나 멀리 루프가 실행 되는가를 정의합니다.

그런 다음 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() 
관련 문제