用python+wxpython写的音乐播放器

musicplay.py

#!/usr/bin python
#-*-coding:utf-8 -*-

import wx
import ConfigParser
import os.path
from Operation import OperationPanel
from Show import ShowPanel


class MainFrame(wx.Frame):
    def __init__(self,parent,id):
        wx.Frame.__init__(self,parent,id,title='music player',size=(380,700),
                          style=wx.DEFAULT_FRAME_STYLE&(~wx.MAXIMIZE_BOX)&(~ wx.RESIZE_BORDER))
      
        self.parser = ConfigParser.ConfigParser()
        self.playlist = None
        self.musiclist = []
        self.musicnames = [] 
        self.initPlayList()
        self.initMusicList()
        
        self.splitter = wx.SplitterWindow(self)
        self.operationPanel = OperationPanel(self.splitter,wx.NewId(),self.playlist,self.musiclist)
        self.showPanel = ShowPanel(self.splitter,wx.NewId(),self.musicnames)
        self.splitter.SplitHorizontally(self.operationPanel,self.showPanel,100)
        self.splitter.SetMinimumPaneSize(100)
        self.initMenuBar()
       
    def initPlayList(self):
        self.parser.read('config.conf')
        self.playlist = str(self.parser.get('PlayList','PlayListDir')) + "/" + str(self.parser.get('PlayList','lastPlayList'))
    
    def initMusicList(self):
        f = open(self.playlist)
        self.musiclist = [x[:-1] for x in f.readlines()] 
        f.close()
        self.musicnames = [os.path.basename(x) for x in self.musiclist]
        
    def initAddMenu(self):
        self.addMenu = wx.Menu()
        self.addFileId = wx.NewId()
        self.addDirId = wx.NewId()
        title_list = [u'文件',u'文件夹']
        self.appendMenuItem(self.addMenu, [self.addFileId,self.addDirId], title_list)
        
    def initDelMenu(self):
        self.delMenu = wx.Menu()
        self.delSelId = wx.NewId()
        self.delDuplicateId = wx.NewId()
        self.delErrId = wx.NewId()
        self.delAllId = wx.NewId()
        self.delPhyicalId = wx.NewId()  
        title_list = [u'选中的文件',u'重复的文件',u'错误的文件','',u'全部删除','',u'物理删除']
        self.appendMenuItem(self.delMenu,
                            [self.delSelId,self.delDuplicateId,self.delErrId,'separator',self.delAllId,'separator',self.delPhyicalId],
                            title_list)
                            
    def initPlayListMenu(self):
        self.playlistMenu = wx.Menu()
        self.newPlayListId = wx.NewId()
        self.addPlayListId = wx.NewId()
        self.openPlayListId = wx.NewId()
        self.savePlayListId = wx.NewId()
        self.delPlayListId = wx.NewId()
        self.saveAllPlayListId = wx.NewId()
        title_list = [u'新建列表',u'添加列表',u'打开列表',u'保存列表',u'删除列表','',u'保存所有列表']
        self.appendMenuItem(self.playlistMenu,
                             [self.newPlayListId,self.addPlayListId,self.openPlayListId,self.savePlayListId,self.delPlayListId,'separator',self.saveAllPlayListId],
                              title_list)
    def initSortMenu(self):
        self.sortMenu = wx.Menu()
        self.sortByFileNameId = wx.NewId()
        self.sortByFilePathId = wx.NewId()
        self.sortByFileTypeId = wx.NewId()
        title_list = [u'按文件名',u'按文件路径',u'按文件类型']
        self.appendMenuItem(self.sortMenu,
                             [self.sortByFileNameId,self.sortByFilePathId,self.sortByFileTypeId],
                              title_list)
    def initFindMenu(self):
        self.findMenu = wx.Menu()
        self.fastLocateId = wx.NewId()
        self.findMusicId = wx.NewId()
        title_list = [u'快速定位',u'查找歌曲']
        self.appendMenuItem(self.findMenu,
                            [self.fastLocateId,self.findMusicId],
                             title_list)
    def initModeMenu(self):
        self.modeMenu = wx.Menu()
        self.single = wx.NewId()
        self.singleCycle = wx.NewId()
        self.sequence = wx.NewId()
        self.cycle = wx.NewId()
        self.random = wx.NewId()
        title_list = [u'单曲播放',u'单曲循环',u'顺序播放',u'循环播放',u'随机播放']
        self.appendMenuItem(self.modeMenu, 
                            [self.single,self.singleCycle,self.sequence,self.cycle,self.random],
                             title_list)
        
    def appendMenuItem(self,menu,id_list,title_list):
        length = len(id_list)
        for i in range(length):
            if id_list[i] == 'separator':
                menu.AppendSeparator()
            else: 
                menu.Append(id_list[i],title_list[i])

    def append2MenuBar(self,menu_list,title_list):
        length = len(menu_list)
        for i in range(length):
            self.menuBar.Append(menu_list[i],title_list[i])
            
    def initMenu(self):
        self.initAddMenu()
        self.initDelMenu()
        self.initPlayListMenu()
        self.initSortMenu()
        self.initFindMenu()
        self.initModeMenu()
        
    def initMenuBar(self):
        self.initMenu()
        self.menuBar = wx.MenuBar()
        self.append2MenuBar(
            [self.addMenu,self.delMenu,self.playlistMenu,self.sortMenu,self.findMenu,self.modeMenu],
            [u'添加',u'删除',u'播放列表',u'排序',u'查找',u'播放模式'])    
        self.SetMenuBar(self.menuBar)
               
if  __name__ == '__main__':
    app = wx.PySimpleApp()
    frame =MainFrame(parent=None,id=wx.NewId())
    frame.Show()
    app.MainLoop()   

Operation.py


#!/usr/bin python
#-*-coding:utf-8 -*-
import wx.media
import os
import ConfigParser
from wx.media import MediaCtrl

wildcard = "mp3 file (*.mp3)|*.mp3|"       \
           "wav file (*.wav)|*.wav|"       \
           "All file (*.*)|*.*"


class CustomPopupWindow(wx.PopupWindow):
    def __init__(self,parent,text='',style=wx.BORDER_NONE):
        wx.PopupWindow.__init__(self,parent,style)
        self.statictext = wx.StaticText(self,label=text)
    
    def SetText(self,text):
        self.statictext.SetLabel(text) 
                  
class OperationPanel(wx.Panel):
    
    def __init__(self,parent,id,playlist,musiclist):
        wx.Panel.__init__(self,parent,id,size=(380,100),
                          style=wx.SUNKEN_BORDER)
        self.allfilepath = musiclist
        self.playlist = playlist
        self.newfilepaths = []
        self.newfilenames = []
        self.count = 0
        self.preIndex = 0
        self.curIndex = 0
        self.nextIndex = 0
        self.volume = 0.0
        self.parser = ConfigParser.ConfigParser()
        self.initConfig()
        self.mc = MediaCtrl(self,style=wx.SIMPLE_BORDER,szBackend=wx.media.MEDIABACKEND_WMP10)
        self.createSlider()
        self.createButton()
        self.bindEvents()
        self.createTimer()
        self.startPlayMusic()
    
    def startPlayMusic(self):
        self.LoadFile(self.allfilepath[self.curIndex])
        
    def initConfig(self):
        self.parser.read('config.conf')
        self.count = int(self.parser.get('Index','count'))
        self.preIndex = int(self.parser.get('Index', 'preIndex'))
        self.curIndex = int(self.parser.get('Index', 'curIndex'))
        self.nextIndex = int(self.parser.get('Index', 'nextIndex'))
        self.workingdir = self.parser.get('Other','LastOpenDir')
        self.volume = self.parser.get('Other','volume')
        self.lastvolume =  self.volume
                                         
    def createSlider(self):
        self.curmusic = wx.StaticText(self,label='test',size=(300,-1),pos=(0,5),style=wx.ALIGN_CENTRE|wx.ST_NO_AUTORESIZE)
        self.progress = wx.StaticText(self,label='00:00',pos=(140,25))
        self.slider = wx.Slider(self,wx.NewId(),pos=(0,40),size=(300,-1))
        self.slider.SetToolTipString(u'播放进度')
        self.volume_slider = wx.Slider(self,wx.NewId(),pos=(320,0),style=wx.SL_VERTICAL|wx.SL_INVERSE)
        self.volume_slider.SetRange(0,100)
        self.volume_slider.SetValue(30)
        self.volume_slider.SetToolTipString(u'音量:%d%%' %self.volume_slider.GetValue())
        
    def createButton(self):
        self.stop_btn = wx.Button(self,wx.NewId(),label=u'停止',pos=(10,65),size=(45,24))
        self.play_btn = wx.Button(self,wx.NewId(),label=u'播放',pos=(60,65),size=(45,24))   
        self.pause_btn = wx.Button(self,wx.NewId(),label=u'暂停',pos=(110,65),size=(45,24))   
        self.pre_btn = wx.Button(self,wx.NewId(),label=u'上一首' ,pos=(160,65),size=(45,24))   
        self.next_btn = wx.Button(self,wx.NewId(),label=u'下一首',pos=(210,65),size=(45,24))
        self.open_btn = wx.Button(self,wx.NewId(),label=u'打开',pos=(260,65),size=(45,24))   
#        self.volume_btn = wx.Button(self,wx.NewId(),label=u'立体声',pos=(260,18),size=(45,20))   
    
    def bindEvents(self):
        self.stop_btn.Bind(wx.EVT_BUTTON,self.OnStop)
        self.play_btn.Bind(wx.EVT_BUTTON,self.OnPlay)   
        self.pause_btn.Bind(wx.EVT_BUTTON,self.OnPause)   
        self.pre_btn.Bind(wx.EVT_BUTTON,self.OnPre)   
        self.next_btn.Bind(wx.EVT_BUTTON,self.OnNext)   
        self.slider.Bind(wx.EVT_SLIDER, self.OnSeek)
        self.volume_slider.Bind(wx.EVT_SCROLL,self.ChangeVolume)
        self.open_btn.Bind(wx.EVT_BUTTON,self.OnOpen)
#        self.volume_btn.Bind(wx.EVT_BUTTON,self.OnVolume)
        self.mc.Bind(wx.media.EVT_MEDIA_LOADED,self.OnMediaLoaded)
        self.mc.Bind(wx.media.EVT_MEDIA_PLAY,self.OnMediaPlay)
        self.mc.Bind(wx.media.EVT_MEDIA_FINISHED,self.OnMediaFinished)
        
    def createTimer(self):
        self.slider_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onUpdateSlider,self.slider_timer)
        self.slider_timer.Start(100)
        self.text_timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.onUpdateText,self.text_timer)

    #stop the song    
    def OnStop(self,event):
        self.mc.Stop()
        
    #play the song 
    def OnPlay(self,event):
        self.Play()
        
    #pause the song      
    def OnPause(self,event):
        self.mc.Pause()
        
    #play the previous song
    def OnPre(self,event):
        self.mc.Stop()
        self.LoadFileByIndex(self.preIndex)
    
    #stop the next song  
    def OnNext(self,event):
        self.mc.Stop()
        self.LoadFileByIndex(self.nextIndex)
    
#    def OnVolume(self,event):
#        if self.volume_btn.GetLabel() == u'立体声':
#            self.volume_slider.SetValue(0)
#            self.setVolumeAndTip()
#            self.volume_btn.SetLabel(u'静音')
#        else:
#            self.volume_slider.SetValue(self.lastvolume)
#            self.setVolumeAndTip()
#            self.volume_btn.SetLabel(u'立体声')
#            
    #play the spcified position of the song 
    def OnSeek(self,event):
        offset = self.slider.GetValue()
        self.mc.Seek(offset)
    
    def OnMediaLoaded(self,event):
        self.Play()
        self.curmusic.SetLabel(os.path.basename(self.allfilepath[self.curIndex])[:-4])
        self.text_timer.Start(1000)
    
    def OnMediaPlay(self,event):
        showpanel = self.GetParent().GetWindow2()
        showpanel.setMusicFocus(self.curIndex)
        
    def OnMediaFinished(self,event):
        self.progress.SetLabel('00:00')
        self.text_timer.Stop()
        if self.count > 0:
            self.curIndex = (self.curIndex+1)%self.count
        self.refreshIndex(0)      
        self.LoadFile(self.allfilepath[self.curIndex])
        
    
    def OnOpen(self,event):
        dlg = wx.FileDialog(
                            self,message='Choose a music file...',
                            defaultDir=self.workingdir,
                            defaultFile='',
                            wildcard=wildcard,
                            style=wx.OPEN | wx.MULTIPLE | wx.CHANGE_DIR)
        if dlg.ShowModal() == wx.ID_OK:
            self.newfilepaths = dlg.GetPaths()
            self.curIndex = self.count
            self.count += len(self.newfilepaths)
            self.refreshIndex(0)
            self.newfilenames = dlg.GetFilenames()
            self.refreshMusicList(self.newfilepaths)
            os.chdir(self.workingdir)#change the working directory to the project
            self.save2File(self.newfilepaths)
            self.LoadFile(self.newfilepaths[0])
            showpanel = self.Parent.GetWindow2()
            showpanel.insert2ListCtrl(self.newfilenames)
            self.newfilepaths = []
            self.newfilenames = []
        dlg.Destroy()
        
    def LoadFile(self,path):
        if not self.mc.Load(path):
            wx.MessageBox("Unable to load %s: Unsupported format?" % path, "ERROR", wx.ICON_ERROR | wx.OK)
        else:
            self.mc.SetVolume(0.3)
            
    def LoadFileByIndex(self,index):
        self.curIndex = index
        self.refreshIndex(0)
        self.LoadFile(self.allfilepath[self.curIndex])
        
    def Play(self):  
        #self.mc.SetPlaybackRate(2)
        self.mc.Play()
        self.slider.SetRange(0, self.mc.Length())

    def ChangeVolume(self,event):
        #volume range is 0.0-1.0
        self.setVolumeAndTip()
        
    #move the silder to show the progress of play music            
    def onUpdateSlider(self, evt):
        offset = self.mc.Tell()
        self.slider.SetValue(offset)  
    
    def onUpdateText(self,evt):
        offset = self.mc.Tell()/1000
        progress_text = '%02d:%02d' %(offset/60,offset%60)
        self.progress.SetLabel(progress_text)
        
    def setVolumeAndTip(self):
        value = self.volume_slider.GetValue()
        self.volume = value/100.0
        if self.volume != 0:
            self.lastvolume = self.volume
        self.mc.SetVolume(self.volume)
        self.volume_slider.SetToolTipString(u'音量:%d%%' %value)
            
    def save2File(self,filepathlist):   
        f = open(self.playlist,'a')
        for filepath in filepathlist:
            f.write(filepath+'\n')
        f.close()
        
    def isEmpty(self):
        f = open(self.mlistfile)
        text = f.readline()
        f.close()
        if not text:
            return True
        else:
            return False
       
    def refreshMusicList(self,filepathlist):
        for filepath in filepathlist:
            self.allfilepath.append(filepath)
    
    def refreshIndex(self,mode):
        """
        mode:the play mode,like recyle,order or random
        """
        if mode == 0:
            self.refreshIndexInMode0()
        elif mode == 1:
            self.refreshIndexInMode1()
        elif mode == 2:
            self.refreshIndexInMode2()
            
    def refreshIndexInMode0(self):
        """
        mode 0:the recyle mode
        """
        if self.count == 1:
            self.preIndex = 0
            self.curIndex = 0
            self.nextIndex = 0  
        #deal with that the selected item is last one
        elif self.curIndex+1 == self.count:
            self.nextIndex = 0
            self.preIndex = self.curIndex - 1
        #deal with that the selected item is first one
        elif self.curIndex == 0:
            self.preIndex = self.count-1
            self.nextIndex = self.curIndex + 1 
        else:
            self.nextIndex = self.curIndex + 1
            self.preIndex = self.curIndex - 1
            
    def refreshIndexInMode1(self):
        pass
    
    def refreshIndexInMode2(self):
        pass
    
    def __del__(self):
        self.parser.read('Config.conf')
        self.parser.set('Index', 'count', self.count)
        self.parser.set('Index','preIndex',self.preIndex)
        self.parser.set('Index','curIndex',self.curIndex)
        self.parser.set('Index','nextIndex',self.nextIndex)
        self.parser.set('Other','LastOpenDir',self.workingdir)
        self.parser.write(open("Config.conf", "w"))

Show.py

#!/usr/bin python
#-*-coding:utf-8 -*-

import wx
import  wx.lib.mixins.listctrl  as  listmix

class TestListCtrl(wx.ListCtrl, listmix.ListCtrlAutoWidthMixin):
    def __init__(self, parent, ID, pos=wx.DefaultPosition,
                 size=wx.DefaultSize,style=wx.LC_REPORT|wx.LC_NO_HEADER|wx.LC_HRULES):
        wx.ListCtrl.__init__(self, parent, ID, pos, size,style)
        listmix.ListCtrlAutoWidthMixin.__init__(self)
        
class ShowPanel(wx.Panel):
    def __init__(self,parent,id,musiclist):
        wx.Panel.__init__(self,parent,id,size=(380,600),
                          style=wx.SUNKEN_BORDER)
        self.curIndex = 0
        self.preIndex = 0
        self.nextIndex = 0
        self.itemcount = 0
        self.initListCtrl()
        self.initListCtrlData(musiclist)
        self.bindEvents()
        self.lastindex = -1
    
    def initListCtrl(self):
        self.playlist = TestListCtrl(self,wx.NewId(),size=(100,600))
        self.playlist.InsertColumn(0,'test',width=100)
        self.playlist.InsertStringItem(0,u'默认')
        
        self.musiclist =TestListCtrl(self,wx.NewId(),pos=(100,0),size=(270,600))
        self.musiclist.InsertColumn(0,'test',width=270)
        #self.musiclist.SetForegroundColour(wx.Colour(0,150,0))
                
    def initListCtrlData(self,musiclist):   
        self.insert2ListCtrl(musiclist)
        
    def insert2ListCtrl(self,data):
        i = self.itemcount
        for item in data:
            self.musiclist.InsertStringItem(i,str(i+1)+'.'+item)
            self.itemcount += 1
            i += 1
            
    def bindEvents(self):
#        self.musiclist.Bind(wx.EVT_LIST_ITEM_SELECTED,self.OnSelected)
        self.musiclist.Bind(wx.EVT_LIST_ITEM_ACTIVATED,self.OnDoubleClick)
        self.musiclist.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK,self.OnRightClickItem)
        
    def OnDoubleClick(self,event):
        index = self.musiclist.GetFirstSelected()
        operationpanel = self.GetParent().GetWindow1()
        operationpanel.LoadFileByIndex(index)
    
    def OnRightClickItem(self,event):
        print 'right click'
        self.createPopMenu()
        
    def createPopMenu(self):
        if not hasattr(self, "popupDel"):
            self.popupDel = wx.NewId()
            self.Bind(wx.EVT_MENU, self.OnDelItem, id=self.popupDel)
        
        menu = wx.Menu()
        menu.Append(self.popupDel,'Delete')
        self.PopupMenu(menu)
        menu.Destroy()
        
    def OnDelItem(self,event):
        pass
        
    def setMusicFocus(self,index):
        if self.lastindex != -1:
            self.musiclist.SetItemTextColour(self.lastindex,'black')
        self.lastindex = index
        self.musiclist.SetItemTextColour(index,'blue')
        

config.conf

[PlayList]
playlistdir = PlayList
lastplaylist = default

[Index]
count = 9
preindex = 4
curindex = 5
nextindex = 6

[Play_Mode]
mode = 0

[Other]
volume = 0.0
lastopendir = C:\Users\chenfeibiao\workspace\wxPythonInAction\src\cfb\musicplayer



开发环境:python2.7+wxpython2.8.12.0

功能:

1.播放mp3,wav类型的音乐,能暂停,停止当前播放的音乐,能切换到上一首,下一首

2.能调节音量

3.拖动播放进度的滚动条,即可将音乐拖到相应的进度并播放

4.通过点击打开按钮,可以添加音乐文件到播放列表


ps:由于近段时间比较忙,所以还有很多功能只是写了开头部分,没有完整实现,而且很多代码都没有优化,等有时间再实现和优化吧。

效果图:


你可能感兴趣的:(python)