我想创建一个带有播放和停止按钮的简单图形用户界面,以便在 python 中播放 mp3 文件。我使用包含 2 个按钮(停止和播放)的 Tkinter 创建了一个非常简单的图形用户界面。
我创建了一个执行以下操作的函数:
def playsound () :
sound = pyglet.media.load('music.mp3')
sound.play()
pyglet.app.run()
我将该函数添加为按钮播放的命令。我还做了一个不同的功能来停止音乐:
def stopsound ():
pyglet.app.exit
我将此功能作为命令添加到第二个按钮。但问题是,当我点击播放时,python 和 gui 卡住了。我可以尝试关闭窗口但它没有关闭,并且停止按钮没有响应。我知道这是因为 pyglet.app.run() 一直执行到歌曲结束,但我该如何防止这种情况呢?当我点击按钮时,我希望 gui 停止播放音乐。关于在哪里可以找到解决方案的任何想法?
最佳答案
您将两个 UI 库混合在一起 - 这本质上并没有什么坏处,但存在一些问题。值得注意的是,他们都需要一个自己的主循环来处理他们的事件。 TKinter 使用它来与桌面和用户生成的事件通信,在这种情况下,pyglet 使用它来播放您的音乐。
这些循环中的每一个都阻止了正常的“自上而下”程序流,正如我们在学习非 GUI 编程时所习惯的那样,程序应该基本上从主循环回调。在这种情况下,在 Tkinter 回调的中间,您启动了 pyglet 主循环(调用 pyglet.app.run
),并且控件永远不会返回到 Tkinter 库。
有时,不同库的循环可以在同一进程中共存,不会发生冲突——当然,您要么运行其中一个,要么运行另一个。如果是这样,则可以在不同的 Python 线程中运行每个库的主循环。
如果它们不能一起存在,你将不得不在不同的进程中处理每个库。
因此,让音乐播放器在另一个线程中启动的一种方法可能是:
from threading import Thread
def real_playsound () :
sound = pyglet.media.load('music.mp3')
sound.play()
pyglet.app.run()
def playsound():
global player_thread
player_thread = Thread(target=real_playsound)
player_thread.start()
如果 Tkinter 和 pyglet 可以共存,那应该足以让您的音乐开始。 但是,为了能够控制它,您需要执行更多操作。我的建议是在 pyglet 线程上有一个回调,由 pyglet 大约每秒调用一次——这个回调检查一些全局变量的状态,并根据它们选择停止音乐、更改正在播放的文件等等上。
关于python - 在 Python 中使用 Pyglet 和 Tkinter 播放音乐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10283067/