Python Pygame/Tkinter音乐播放器:时间滑块导致音频起伏

Python Pygame/Tkinter音乐播放器:时间滑块导致音频起伏,python,tkinter,pygame,mixer,Python,Tkinter,Pygame,Mixer,我正在用Pygame&Tkinter构建一个音乐播放器,目前正在尝试添加一个工作时间滑块,允许您通过拖动滑块跳到歌曲中的特定点 我将滑块末端的值('to'在配置中)设置为当前歌曲的长度,然后使用'after'更新滑块,如下所示: def update_timeslider(self, _ = None): time = (pygame.mixer.music.get_pos()/1000) timeslider.set(time) self.after(1000, sel

我正在用Pygame&Tkinter构建一个音乐播放器,目前正在尝试添加一个工作时间滑块,允许您通过拖动滑块跳到歌曲中的特定点

我将滑块末端的值('to'在配置中)设置为当前歌曲的长度,然后使用'after'更新滑块,如下所示:

def update_timeslider(self, _ = None):
    time = (pygame.mixer.music.get_pos()/1000)
    timeslider.set(time)
    self.after(1000, self.update_timeslider)
这在随着歌曲的时间移动滑块时起作用,但现在我正在尝试实现提示功能,出现了一些问题。我尝试用鼠标将歌曲位置更新为滑块的值

def cue(self, _ = None):
    pygame.mixer.music.set_pos(timeslider.get()) 
现在,当我演奏这首歌时,它非常起伏。当我移动滑块时,它会在“after”函数更新之前工作一秒钟,但随后它会跳回到移动之前的位置。我试着提高刷新率,但这只会使它跳得更快,并且仍然像以前一样波涛汹涌

有更好的方法吗

完整代码:

import os
import pygame
import tkinter
from tkinter.filedialog import askdirectory
from tkinter import *
from tkinter import ttk

playlist = [] 
index = 0
paused = False

class Application(tkinter.Tk):
    def __init__(self, parent):
        tkinter.Tk.__init__(self, parent)
        self.minsize(400,400)
        self.parent = parent
        self.main()

    def main(self):
        global v
        global songlabel
        global listbox
        global volumeslider
        global timeslider
        global time_elapsed
        global songlength

        self.configure(background='grey')
        self.grid()
        self.listbox = Listbox(self, width=20, height=25, relief='ridge', bd=3)
        self.listbox.grid(padx=30, pady=15, row=1, columnspan=11, sticky='NSEW')

        v = StringVar()
        songlabel = tkinter.Label(self, textvariable=v, width=30, anchor="n")

        rewbtn = PhotoImage(file="rew.gif")
        stopbtn = PhotoImage(file="stop.gif")
        playbtn = PhotoImage(file="play.gif")
        pausebtn = PhotoImage(file="pause.gif")
        ffbtn = PhotoImage(file="ff.gif")

        prevbutton = Button(self, width=30, height=30, image=rewbtn, anchor='w')
        prevbutton.image = rewbtn
        prevbutton.bind("<Button-1>", self.prevsong)
        prevbutton.grid(row=10, column=0, padx=(30,0), sticky='w')

        playbutton = Button(self, width=30, height=30, image=playbtn, anchor='w')
        playbutton.image = playbtn
        playbutton.bind("<Button-1>", self.play)
        playbutton.grid(row=10, column=1, sticky='w')

        pausebutton = Button(self, width=30, height=30, image=pausebtn, anchor='w')
        pausebutton.image = pausebtn
        pausebutton.bind("<Button-1>", self.pause)
        pausebutton.grid(row=10, column=2, sticky='w')

        stopbutton = Button(self, width=30, height=30, image=stopbtn, anchor='w') 
        stopbutton.image = stopbtn
        stopbutton.bind("<Button-1>", self.stop)
        stopbutton.grid(row=10, column=3, sticky='w')

        nextbutton = Button(self, width=30, height=30, image=ffbtn, anchor='w')
        nextbutton.image = ffbtn
        nextbutton.bind("<Button-1>", self.nextsong)
        nextbutton.grid(row=10, column=4, sticky='w')

        volumeslider = Scale(self, from_=0, to = 1, resolution = 0.01, orient = HORIZONTAL, showvalue = 'yes', command = self.change_vol)
        volumeslider.grid(row=10, column=8, columnspan=3, padx=30, pady=(0,10), sticky='wse')
        volumeslider.set(50)

        timeslider = Scale(self, from_=0, to=100, resolution=1, orient=HORIZONTAL, showvalue = 'no', command=self.cue) 
        timeslider.grid(row=12, column=0, columnspan=11, padx = 30, sticky='wse')
        timeslider.set(0)

        time_elapsed = Label(text="0:00:00")
        time_elapsed.grid(row=13, columnspan=11, padx=(30,0), pady=(0,30), sticky='ws')
        # time_remaining = Label(text="0:00:00")
        # time_remaining.grid(row=13, column = 7, columnspan=5, padx=(0,30), pady=(0,30), sticky='se')

    # FILE OPEN
        self.directorychooser()
        playlist.reverse()
        for items in playlist:
            self.listbox.insert(0, items)
        playlist.reverse()
        self.listbox.bind("<Double-Button-1>", self.selectsong)
        self.listbox.bind("<Return>", self.selectsong)
        songlabel.grid(row = 0, column = 0, columnspan = 10, padx = 55, pady=(10,0), sticky=W+N+E)

    # GRID WEIGHT
        self.grid_columnconfigure(5,weight=1)
        self.grid_columnconfigure(7,weight=1)
        self.grid_rowconfigure(1,weight=1)


    def prevsong(self, event):
        global index

        if index > 0:
            index-=1
            print(index)
        elif index == 0:
            index = len(playlist)-1

        pygame.mixer.music.load(playlist[index])
        self.set_timescale()
        pygame.mixer.music.play()
        self.get_time_elapsed()
        self.update_timeslider()
        self.update_currentsong()


    def play(self, event):
        self.set_timescale()        
        pygame.mixer.music.play()
        self.get_time_elapsed()
        self.update_timeslider()
        self.update_currentsong()


    def pause(self, event): 
        global paused
        if paused == True:
            pygame.mixer.music.unpause()
            paused = False
        elif paused == False:
            pygame.mixer.music.pause()
            paused = True


    def nextsong(self, event):
        global index

        if index < len(playlist)-1:
            index+=1
        elif index == (len(playlist)-1):
            index = 0
        pygame.mixer.music.load(playlist[index])
        self.set_timescale()
        pygame.mixer.music.play()
        self.get_time_elapsed()
        self.update_timeslider()
        self.update_currentsong()


    def stop(self, event):
        pygame.mixer.music.stop()
        v.set("")
        return songlabel


    def selectsong(self, event):
        global index
        global songtime
        global songlength

        idx = self.listbox.curselection()
        index = idx[0]
        pygame.mixer.music.load(playlist[index])

        self.set_timescale()
        pygame.mixer.music.play()
        self.get_time_elapsed()
        # self.get_time_remaining()
        self.update_timeslider()
        self.update_currentsong()


    def change_vol(self, _ = None):
        pygame.mixer.music.set_volume(volumeslider.get())


    def cue(self, _ = None):
        pygame.mixer.music.set_pos(timeslider.get())


    def getsonglen(self):
        s = pygame.mixer.Sound(playlist[index])
        songlength = s.get_length()
        return songlength


    def set_timescale(self):
        songlength = self.getsonglen()
        timeslider.config(to=songlength)    


    def get_time_elapsed(self):
        global time_elapsed
        time = int(pygame.mixer.music.get_pos()/1000)
        m, s = divmod(time, 60)
        h, m = divmod(m, 60)
        clock = "%d:%02d:%02d" % (h, m, s)
        time_elapsed.configure(text=clock)
        self.after(100, self.get_time_elapsed)

    # def get_time_remaining(self):
    #   global time_remaining
    #   time = int(pygame.mixer.music.get_pos()/1000)
    #   songlen = int(self.getsonglen())
    #   rem = songlen - time
    #   m, s = divmod(rem, 60)
    #   h, m = divmod(m, 60)
    #   clock2 = "%d:%02d:%02d" % (h, m, s)
    #   time_remaining.configure(text=clock2)
    #   self.after(100, self.get_time_remaining)


    def update_timeslider(self, _ = None):
        time = (pygame.mixer.music.get_pos()/1000)
        timeslider.set(time)
        self.after(10, self.update_timeslider)


    def update_currentsong(self):
        global index
        global songlabel
        v.set(playlist[index])
        return songlabel


    def directorychooser(self):
        directory = askdirectory()
        os.chdir(directory)
        for files in os.listdir(directory):
            if files.endswith(".flac"):
                realdir = os.path.realpath(files)
                playlist.append(files)
                print(files)
        pygame.mixer.init()
        pygame.mixer.music.load(playlist[0])
        self.update_currentsong()

app = Application(None)
app.mainloop()
导入操作系统
导入pygame
进口tkinter
从tkinter.filedialog导入askdirectory
从tkinter进口*
从tkinter导入ttk
播放列表=[]
索引=0
暂停=错误
类应用程序(tkinter.Tk):
定义初始化(自身,父级):
tkinter.Tk.\uuuuu init\uuuuuu(自,父)
self.minsize(400400)
self.parent=parent
self.main()
def主(自):
全球v
全球歌曲标签
全局列表框
全局体积滑块
全球时间滑块
全局时间
全球歌曲长度
自我配置(背景为灰色)
self.grid()
self.listbox=listbox(self,宽度=20,高度=25,浮雕=ridge',bd=3)
self.listbox.grid(padx=30,pady=15,row=1,columnspan=11,sticky='NSEW')
v=StringVar()
songlabel=tkinter.Label(self,textvariable=v,width=30,anchor=“n”)
rewbtn=PhotoImage(file=“rew.gif”)
stopbtn=PhotoImage(file=“stop.gif”)
playbtn=PhotoImage(file=“play.gif”)
pausebtn=PhotoImage(file=“pause.gif”)
ffbtn=PhotoImage(file=“ff.gif”)
prevbutton=按钮(自身,宽度=30,高度=30,图像=rewbtn,锚定=w')
prevbutton.image=rewbtn
prevbutton.bind(“,self.prevsong)
网格(行=10,列=0,padx=(30,0),粘性=w')
playbutton=按钮(self,宽=30,高=30,image=playbtn,anchor='w')
playbutton.image=playbtn
playbutton.bind(“,self.play)
playbutton.grid(行=10,列=1,粘性=w')
pausebutton=按钮(自身,宽度=30,高度=30,图像=pausebtn,锚定=w')
pausebutton.image=pausebtn
pausebutton.bind(“,self.pause)
pausebutton.grid(行=10,列=2,粘性=w')
stopbutton=按钮(自身,宽度=30,高度=30,图像=stopbtn,锚点=w')
stopbutton.image=stopbtn
stopbutton.bind(“,self.stop)
stopbutton.grid(行=10,列=3,粘性=w')
下一个按钮=按钮(自身,宽度=30,高度=30,图像=ffbtn,锚定=w')
nextbutton.image=ffbtn
nextbutton.bind(“,self.nextsong)
网格(行=10,列=4,粘性=w')
volumeslider=Scale(self,from=0,to=1,分辨率=0.01,方向=水平,showvalue=yes,command=self.change\u vol)
volumeslider.grid(行=10,列=8,列span=3,padx=30,pady=(0,10),sticky='wse')
体积滑块组(50)
timeslider=Scale(self,from=0,to=100,分辨率=1,方向=水平,showvalue=no,command=self.cue)
timeslider.grid(行=12,列=0,列span=11,padx=30,sticky='wse')
时间滑块设置(0)
时间=标签(text=“0:00:00”)
网格(行=13,列span=11,padx=(30,0),pady=(0,30),sticky='ws')
#剩余时间=标签(text=“0:00:00”)
#剩余时间网格(行=13,列=7,列span=5,padx=(0,30),pady=(0,30),sticky='se')
#文件打开
self.directorychooser()
playlist.reverse()
对于播放列表中的项目:
self.listbox.insert(0,项)
playlist.reverse()
self.listbox.bind(“,self.selectsong)
self.listbox.bind(“,self.selectsong)
网格(行=0,列=0,列span=10,padx=55,pady=(10,0),粘性=W+N+E)
#网格重量
self.grid\u column配置(5,权重=1)
self.grid\u column配置(7,权重=1)
self.grid_rowconfigure(1,权重=1)
def prevsong(自我、事件):
全球指数
如果索引>0:
索引-=1
打印(索引)
elif索引==0:
索引=len(播放列表)-1
pygame.mixer.music.load(播放列表[索引])
self.set_timescale()
pygame.mixer.music.play()
self.get_time_passed()
self.update_timeslider()
self.update_currentsong()
def播放(自我、事件):
self.set_timescale()
pygame.mixer.music.play()
self.get_time_passed()
self.update_timeslider()
self.update_currentsong()
def暂停(自身、事件):
全局暂停
如果暂停==真:
pygame.mixer.music.unpuse()
暂停=错误
elif暂停==错误:
pygame.mixer.music.pause()
暂停=真
def nextsong(自我、事件):
全球指数
如果索引self.update_timeslider()
class Application(tkinter.Tk):
    def __init__(self, parent):
        ...
        self.after_id = None

    def update_timeslider(self, _ = None):
        if self.after_id is not None:
            self.after_cancel(self.after_id)
            self.after_id = None

        time = (pygame.mixer.music.get_pos()/1000)
        timeslider.set(time)
        self.after_id = self.after(1000, self.update_timeslider)