如何在Pyglet中连续播放音乐(同时使用tkinter)?

2024-05-14 03:44:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图通过制作播放列表在游戏中播放一些音乐,当音乐结束时,下一个开始。。。经过几个小时的寻找,我仍然找不到一个解决方案。。。 我知道如何播放一首音乐以及如何使用next\u source播放下一首音乐,但我不知道如何让它在音乐结束时自动播放。这就是我来这里的原因。 我发现很多网站/论坛都告诉你在eos上使用,但我就是做不到

player = pyglet.media.Player()
music1 = pyglet.media.load('somemusic.wav')
music2 = pyglet.media.load('someothermusic.wav')
player.queue(music1)
player.queue(music2)

#the part i'm struggling with (I've tried that)

player.on_eos = pyglet.media.Player.on_eos
@player.event
def on_eos():
    #some function
    print("on player eos")

player.push_handlers(on_eos)

#

player.play()

Tags: 游戏queue音乐onloadmedia播放列表pyglet
2条回答
player = pyglet.media.Player()
music1 = 'somemusic.wav'
music2 = 'someothermusic.wav'
music = [music1, music2]

@player.event
def on_eos():
    print("[event] on_eos: end of file")

@player.event
def on_player_eos():
    print("[event] on_player_eos: end of queue")

media = []
for filename in music:
    print('load:', filename)
    item = pyglet.media.load(filename)
    media.append(item)

def create_queue():
    for item in media:
        print('queue:', item)
        player.queue(item)

def play():
    create_queue()
    player.play()

def update(event):
    root.update()

def on_close():
    clock.unschedule(update)
    root.destroy()  #edit:useless  > It even creates problems!
    pyglet.app.exit()  #this line does the work without the previous one

is_paused = False

root.protocol("WM_DELETE_WINDOW", on_close)

clock.schedule(update)

这给了我一个错误:TypeError:queue()缺少1个必需的位置参数:“source”#edit:no more(已解决),问题出在其他地方

播放按钮:

Button(StartPage, text="Play", command=play).pack()

注意:如果您像我一样将键绑定到函数(使用tkinter),并且它们不再工作,请使用window.focus\u force()它将解决您的问题

如果运行正确,您必须在代码末尾使用pyglet.app.run()。它将运行event loop,运行播放下一首音乐的代码。它还将运行分配给on_eos等的代码

import pyglet

files = [
    'somemusic1.wav',
    'somemusic2.wav',
    'somemusic3.wav',
]
    
player = pyglet.media.Player()

@player.event
def on_eos():
    print("[event] on_eos: end of file")

@player.event
def on_player_eos():
    print("[event] on_player_eos: end of queue")

musics = []

for filename in files:
    item = pyglet.media.load(filename) 
    musics.append( item )
    print('load:', filename)
    
    player.queue(item)
    print('queue:', item)

player.play()

pyglet.app.run()  # need it to run `event loop` 

如果您想使用tkinter运行它,那么这可能是个问题,因为pyglet运行事件循环pyglet.app.run(),它会阻止代码,而tkinter必须运行自己的事件循环root.mainloop(),它也会阻止代码。其中一个循环必须在单独的线程中运行—类似于Playing music with Pyglet and Tkinter in Python中的答案

我尝试使用这个代码的线程,但当我按下^{中的按钮时,我只播放了第一首音乐。所以我辞职了

我还尝试在piglet中构建自己的循环(请参见并添加root.update()而不是root.mainloop(),但它需要更多的东西才能正常工作。因此我辞职了

while True:
    pyglet.clock.tick()

    for window in pyglet.app.windows:
        window.switch_to()
        window.dispatch_events()
        window.dispatch_event('on_draw')
        window.flip()
    root.update()

对我来说,最好的解决方案是使用PyQt,它用于创建GUI,它有许多wigdet和许多类用于其他任务

我使用了一些带有QMediaPlayerQMediaPlaylist的示例代码,在单击按钮后逐个运行所有音乐。它还具有更改volume的功能,但我没有测试它

它不仅可以加载声音,还可以加载可以在QVideoWidget中显示的视频。它还可以直接从internet(URL)加载文件

from PyQt5.QtMultimediaWidgets import QVideoWidget
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QPushButton
from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer, QMediaPlaylist
import sys

files = [
    'somemusic1.wav',
    'somemusic2.wav',
    'somemusic3.wav',    
]
    
class VideoPlayer:

    def __init__(self):
        #self.video = QVideoWidget()
        #self.video.resize(300, 300)
        #self.video.move(0, 0)
        
        self.playlist = QMediaPlaylist()
        
        for item in files:
            self.playlist.addMedia(QMediaContent(QUrl.fromLocalFile(item)))
        
        self.playlist.setCurrentIndex(1)
        
        self.player = QMediaPlayer()
        #self.player.setVideoOutput(self.video)      
        self.player.setPlaylist(self.playlist)

    def callback(self):
        self.player.setPosition(0) # to start at the beginning of the video every time
        #self.video.show()
        self.player.play()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    v = VideoPlayer()
    b = QPushButton('start')
    b.clicked.connect(v.callback)
    b.show()
    sys.exit(app.exec_())

编辑:

我使用Pyglettkinter创建了工作代码,使用pyglet.clock.schedule()定期运行root.update()

import pyglet
from pyglet import clock
import tkinter as tk

files = [
    'somemusic1.wav',
    'somemusic2.wav',
    'somemusic3.wav',    
]
    
player = pyglet.media.Player()

@player.event
def on_eos():
    print("[event] on_eos: end of file")

@player.event
def on_player_eos():
    print("[event] on_player_eos: end of queue")

media = []

# load files
for filename in files:
    print('load:', filename)
    item = pyglet.media.load(filename) 
    media.append( item )


def create_queue():
    # create queue
    for item in media:
        print('queue:', item)
        player.queue(item)

#  - tkitner  -

def play():
    create_queue()
    player.play()

def update(event): # `schedule` sends `event` but `root.update` doesn't get any arguments
    root.update() 

def on_close():
    clock.unschedule(update)
    root.destroy()
    pyglet.app.exit()
            
is_paused = False

root = tk.Tk()

root.protocol("WM_DELETE_WINDOW", on_close)

tk.Button(root, text="Play", command=play).pack()
tk.Button(root, text="Exit", command=on_close).pack()

clock.schedule(update)

pyglet.app.run()  # need it to run `event loop`