繁体   English   中英

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

[英]How to play music continuously in Pyglet (using tkinter at the same time)?

我试图通过制作一个播放列表在我的游戏中加入一些音乐,当音乐结束时,下一个音乐开始......经过几个小时寻找解决方案我仍然找不到......我知道如何玩一个音乐以及如何使用next_source播放下一个,但我不知道如何让它在音乐结束时自动播放。 这就是我在这里的原因。 我发现许多网站/论坛告诉您使用on_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()
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() missing 1 required positional argument: 'source' #edit: no more(solved),问题出在其他地方。

播放按钮:

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

注意:如果您像我一样将键绑定到功能(使用 tkinter)并且它们不再起作用,请使用window.focus_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()也会阻塞代码。 此循环之一必须在单独的线程中运行-类似于在Python 中使用 Pyglet 和 Tkinter 播放音乐中的答案

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

我也尝试在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 ,它有许多 wigdets 和许多用于其他任务的类。

单击按钮后,我使用了一些示例代码与QMediaPlayerQMediaPlaylist一起运行所有音乐。 它也有 function 来改变volume ,但我没有测试它。

它不仅可以加载声音,还可以加载可以在QVideoWidget中显示的视频。 它可以直接从互联网(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` 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM