[英]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 和許多用於其他任務的類。
單擊按鈕后,我使用了一些示例代碼與QMediaPlayer
和QMediaPlaylist
一起運行所有音樂。 它也有 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_())
編輯:
我用Pyglet
和tkinter
創建了工作代碼,使用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.