筆者工做業餘時間也沒什麼愛好,社交圈子也小,主要娛樂就是揹着本身帶電瓶的賣唱音響到住地附近找我的多的位置唱唱KtV。html
硬件上點歌就用筆記本電腦,歌曲都是網上下載的mkv格式的含有兩個音軌的視頻。所以點歌軟件成了筆者的需求。python
點歌軟件需求極簡單:編程
以前已經用多種開發工具寫過,此次逢學習python的機會用它再寫一個python版。c#
軟件界面以下:api
雙擊啓動播放器。app
就代碼量上和用筆者用C#寫的相同功能的軟件對比下:ide
C#版軟件提供的功能與本例子是徹底相同。工做邏輯代碼約230行,設計器代碼(界面代碼,系統自動生成)約210行,還不算漢字轉拼音類的代碼。函數式編程
python版界面加工做邏輯代碼一塊兒約150行。也所以,筆者在編寫python版的music時,明顯感受到python的代碼精練濃縮(況且筆者只是初學python幾天)。函數
c#版的相同功能的軟件工具
完整的代碼以下(python3.6.1環境下開發):
1 from tkinter import * 2 import tkinter.messagebox as messagebox 3 from xpinyin import Pinyin 4 import os 5 import win32api 6 import win32con 7 8 class music(): 9 __musicPlayPath='D:\\Program Files (x86)\\SPlayer\\splayer.exe' 10 __userMusicDiskFilePath='D:\\usermusic.txt' 11 __musicDefaultList=[] 12 musicCurList=[] 13 __userSelMusicList=[] 14 def __init__(self,musicPath): 15 self.__musicPath=musicPath 16 17 def delUserMusicListItem(self,item): 18 if item in music.__userSelMusicList: 19 music.__userSelMusicList.remove(item) 20 messagebox.showinfo('提示','刪除成功!') 21 22 def addUserMusicListItem(self,item): 23 if not(item in music.__userSelMusicList): 24 music.__userSelMusicList.append(item) 25 26 def readUserMuslicList(self): 27 return music.__userSelMusicList 28 29 def getSerachList(self): 30 return music.musicCurList 31 32 def setDefaultMuslic(self): 33 music.__musicDefaultList = self.readMusicFromDisk() 34 35 def readDefaultMuslic(self): 36 return music.__musicDefaultList 37 38 def getMusicListByUserKey(self,searchTxt): 39 print(searchTxt) 40 if str(searchTxt).__len__()<1: 41 music.musicCurList=music.__musicDefaultList[:] 42 return 43 music.musicCurList.clear() 44 p = Pinyin() 45 for m in music.__musicDefaultList: 46 py = p.get_initials(m, '') 47 if (py.upper()).find(searchTxt.upper())>=0: 48 music.musicCurList.append(m) 49 50 def saveUserMusicListToDisk(self): 51 f=open(music.__userMusicDiskFilePath,'w') 52 tmpAry=music.__userSelMusicList[:] 53 def addReturn(x): 54 return x+'\n' 55 f.writelines(map(addReturn, tmpAry)) 56 f.close() 57 58 def loadUserMusicListFromDisk(self): 59 self.ifNotFileExistCreateEmptyFile() 60 f=open(music.__userMusicDiskFilePath,'r') 61 music.__userSelMusicList.clear() 62 tmpAry=f.readlines() 63 def delReturn(x): 64 return x[0:len(x)-1] 65 music.__userSelMusicList=list(map(delReturn, tmpAry)) 66 f.close() 67 68 def ifNotFileExistCreateEmptyFile(self): 69 if not(os.path.exists(music.__userMusicDiskFilePath)): 70 f = open(music.__userMusicDiskFilePath, 'a') 71 f.close() 72 73 def readMusicFromDisk(self): 74 music.__musicDefaultList= [d for d in os.listdir(self.__musicPath) if d.upper().find(".MKV")>=0] 75 return music.__musicDefaultList 76 77 def playMusic(self,event): 78 w = event.widget 79 index = int(w.curselection()[0]) 80 value = w.get(index) 81 win32api.ShellExecute(0, 'open', music.__musicPlayPath, 82 '\"'+ self.__musicPath+value+'\"', '', 1) 83 84 class gui(music): 85 86 def __init__(self,winName): 87 self.winName=winName 88 self._music__musicPath='D:\\KuGou\\' 89 self.lbx = StringVar() 90 91 def addMusicToUserList(self): 92 index = int(self.listbox1.curselection()[0]) 93 value = self.listbox1.get(index) 94 print(value) 95 self.addUserMusicListItem(value) 96 self.saveUserMusicListToDisk() 97 messagebox.showinfo('成功','已經添加歌曲 \"'+value+'\"!') 98 99 def UpdateUserMusicList(self): 100 self.lbx.set(self.readUserMuslicList()) 101 102 def searchMusic(self,event): 103 w = event.widget 104 txt = w.get() 105 self.getMusicListByUserKey(txt) 106 self.lbx.set(self.getSerachList()) 107 108 def delUserMusic(self): 109 index = int(self.listbox1.curselection()[0]) 110 value = self.listbox1.get(index) 111 self.delUserMusicListItem(value) 112 self.lbx.set(self.readUserMuslicList()) 113 self.saveUserMusicListToDisk() 114 115 def allmusic(self): 116 self.lbx.set(self.readDefaultMuslic()) 117 118 def initForm(self): 119 self.winName.title("music v1.0 by 劉小勇") 120 self.winName.geometry('600x480+10+10') 121 self.winName['bg']="pink" 122 self.winName.resizable(width=False,height=False) 123 124 self.btn1=Button(self.winName,text='所有歌曲',bg='lightblue',command=self.allmusic) 125 self.btn1.grid(row=1,column=1) 126 self.btn2=Button(self.winName,text='選中的歌曲',bg='lightblue',command=self.UpdateUserMusicList) 127 self.btn2.grid(row=1,column=2) 128 self.btn3=Button(self.winName,text='添加到選中的歌曲',bg='lightyellow',command=self.addMusicToUserList) 129 self.btn3.grid(row=1,column=3) 130 self.btn4=Button(self.winName,text='刪除歌曲',bg='lightyellow',command=self.delUserMusic) 131 self.btn4.grid(row=1,column=4) 132 133 self.lab1=Label(self.winName,text='搜索:') 134 self.lab1.grid(row=1,column=5) 135 self.txt1=Entry(self.winName, width=20) 136 self.txt1.bind('<Return>',self.searchMusic) 137 self.txt1.grid(row=1,column=6) 138 139 self.scrollbar = Scrollbar() 140 self.scrollbar.grid(row=2,column=13,rowspan=13,sticky='NS') 141 self.listbox1=Listbox(self.winName,listvariable=self.lbx,width = 82,height=25,yscrollcommand=self.scrollbar.set) 142 self.setDefaultMuslic(); 143 self.lbx.set(self.readDefaultMuslic()) 144 self.listbox1.bind('<Double-Button-1>',self.playMusic) 145 self.listbox1.grid(row=2,column=1,columnspan=12) 146 self.scrollbar.config(command=self.listbox1.yview) 147 self.loadUserMusicListFromDisk() 148 149 150 tk=Tk() 151 form=gui(tk) 152 form.initForm() 153 tk.mainloop()
在編碼過程當中研究過的一些知識點聚集以下:
1. 如何在搜索框觸發搜索後更新listbox, 這個是利用tkinter的 StringVar()
參考筆者貼子:Python tkinter 控件更新信息
2. 控件listbox的滾動條
參考筆者貼子:python tkinter Listbox用法
3. 控件的事件綁定
參考筆者貼子:python tkinter教程-事件綁定
4. 控件的佈局
參考筆者貼子:python tkinter學習——佈局
5. 高階函數
參考筆者貼子:python 函數式編程:高階函數,map/reduce
6. 漢字轉拼音
參考筆者貼子:Python漢字轉換成拼音
7. win32模塊
參考筆者貼子:Python中四種運行其餘程序的方式
筆者寫python程序時的開發ide集成環境是pycharm,在寫tkinter代碼時,關於控件的屬性沒有什麼有意義的提示。由於去記住控件屬性的完整拼寫是不容易也是沒有意義的事。
這也是寫界面代碼比較麻煩的地方。
長期依賴visual studio c#的IDE強大的語法提示、拼寫補全功能, 已經讓筆者手工編碼的能力高度退化,對於沒有屬性提示的編程環境已經沒法想像。
原創文章,出處 : http://www.cnblogs.com/hackpig/