如何使用 Tkinter 按钮打破无限循环?



我正在使用一个程序,我将Tkinter用于UI。我正在编写一个代码来重复播放音频。我正在使用pygame.mixer.music()播放音频。

在UI中,我创建了两个按钮("开始"和"停止")。我将一个包含循环结构的方法附加到开始按钮,以便当按下开始按钮时,循环将被执行并开始重复播放音频。现在我不知道如何附加停止按钮。例如,当按下停止按钮时,控件应退出循环。我可以使用中断或其他类似的东西吗?我对中断的概念完全陌生。要继续这样做,请帮助我解决哪种中断,该库是什么等。如果没有,请帮助我如何使用停止按钮。

这是我的代码:

from pygame import *
from Tkinter import *
import time
root = Tk()
root.geometry("1000x200")
root.title("sampler")
m=1
n=1
mixer.init()
def play():
while m==1:
print 'playing'
mixer.music.load('audio 1.mp3')
mixer.music.play()
time.sleep(n)
start = Button(root, text="play", command = play)
start.pack()
stop = Button(root, text="Stop")
stop.pack()
mainloop()

n定义每个循环应播放音频的时间长度。

Python 并不完全支持中断,最接近的可能是某种信号处理程序,通过其signal库支持。但是,它们可能无法很好地与 Tkinter(或pygame)配合使用,所以我认为这不是一个好方法——而且无论如何它们并不是真正必要的,因为您想做的事情可以在 Tkinter 的mainloop()内处理。

虽然看起来有些复杂,但我建议实现它的方法是将大部分播放控制功能封装在单个 Pythonclass中。这将减少全局变量的使用,这将使程序更容易调试和进一步开发(因为面向对象编程的许多优点 - 也称为OOP)。

下面说明了我的意思。请注意,我使用的是Python 3,因此必须对您的代码进行一些额外的更改才能与该版本一起使用。我不确定,但这个版本也应该在 Python 2 中工作,除了你需要按照指示更改 Tkinter 模块的import

from pygame import *
from tkinter import *  # Change to "from Tkinter import *" for Python 2.x.
class PlayController(object):
def __init__(self, mixer, music_filename, polling_delay):
self.mixer = mixer
self.music_filename = music_filename
self.polling_delay = polling_delay  # In milliseconds.
self.playing = False
def play(self):
if self.playing:
self.stop()
self.mixer.music.load(self.music_filename)
self.mixer.music.play(-1)  # -1 means to loop indefinitely.
self.playing = True
root.after(self.polling_delay, self.check_status)  # Start playing check.
def stop(self):
if self.playing:
self.mixer.music.stop()
self.playing = False
def check_status(self):
if self.playing:
print('playing')
root.after(self.polling_delay, self.check_status)  # Repeat after delay.
root = Tk()
root.geometry("1000x200")
root.title("Sampler")
mixer.init()
play_control = PlayController(mixer, 'tone.wav', 1000)
Button(root, text="Play", command=play_control.play).pack()
Button(root, text="Stop", command=play_control.stop).pack()
mainloop()

您需要向按钮添加命令...stop = Button(root, text="Stop", command=stop)

仅添加停止命令可能不起作用,因为无限循环的结构方式,在单击播放时无法与 tkinter 界面进行交互。尝试像这样重组您的程序:

from Tkinter import *
from pygame import *
import time
import threading
switch = True
root = Tk()
n = 1
mixer.init()
root.geometry("1000x200")
root.title("sampler")

def play():
def run():
while switch:
print 'playing'
mixer.music.load('audio 1.mp3')
mixer.music.play()
time.sleep(n)
if not switch:
break
thread = threading.Thread(target=run)
thread.start()

def switch_on():
global switch
switch = True
play()

def switch_off():
global switch
switch = False

def kill():
root.destroy()

onbutton = Button(root, text="Play", command=switch_on)
onbutton.pack()
offbutton = Button(root, text="Stop", command=switch_off)
offbutton.pack()
killbutton = Button(root, text="Kill", command=kill)
killbutton.pack()
root.mainloop()

这样,tkinter 按钮在单独的线程上运行,因此当一个按钮循环时,您仍然可以与另一个进行交互。

最新更新