zoukankan      html  css  js  c++  java
  • Python Tkinter 学习成果:点歌软件music

    笔者工作业余时间也没什么爱好,社交圈子也小,主要娱乐就是背着自己带电瓶的卖唱音响到住地附近找个人多的位置唱唱KtV。

    硬件上点歌就用笔记本电脑,歌曲都是网上下载的mkv格式的含有两个音轨的视频。因此点歌软件成了笔者的需求。

    点歌软件需求极简单:

    • 读磁盘上的目录取全部music,双击则调用播放器播放music。
    • 自己常唱的歌曲可以选到自选歌曲列表。
    • 支持按简拼搜索music

    之前已经用多种开发工具写过,这次逢学习python的机会用它再写一个python版。

    软件界面如下:

     

     双击启动播放器。

    就代码量上和用笔者用C#写的相同功能的软件对比下:

    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+'
    '
     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/

  • 相关阅读:
    RabbitMQ学习笔记
    Eclipse下JRebel的安装和基本使用
    通过HTTP响应头让浏览器自动刷新
    CentOS6.5安装Jenkins
    Windows快捷操作技巧
    关于代码压缩混淆加密整理;
    一款优雅的小程序拖拽排序组件实现
    记一次 Mac CA证书 问题
    微信小程序-Swiper和下拉刷新组件
    WeUI Picker组件 源代码分析
  • 原文地址:https://www.cnblogs.com/hackpig/p/8227392.html
Copyright © 2011-2022 走看看