簡體   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