我用 Python 写了一款炫酷音乐播放器,想听啥随便搜!

news/2024/11/18 8:39:29/

作者:Dragon少年

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/hhladminhhl/article/details/118915410

昨天晚上坐在电脑面前,想着一边撸代码,一边听音乐。搜了搜自己想听的歌,奈何好多歌曲都提示需要版权,无法播放!

没办法,想听歌还是得靠自己解决!今天就一起用python自制一款炫酷的音乐播放器吧~

首先一起来看看最终实现的音乐播放器效果:

下面,我们开始介绍这个音乐播放器的制作过程。

一、核心功能设计

总体来说,我们首先需要设计UI界面,对播放器的画面布局进行排版设计;其次我们的这款音乐播放器的主要功能包括根据关键字搜索自动爬取音乐,获取音乐列表,能进行音乐播放。

当然还少不了一些附加功能,例如播放方式列表循环、单曲循环、随机播放,当前上一首下一首播放,播放暂停开始,音量增加减少,播放历史查看等。

拆解需求,大致可以整理出核心功能如下:

UI设计排版布局

  • 头部主要包括关键字搜索和音乐来源选择,以及窗体最小化,最大化,关闭功能

  • 中间主体包含左右两侧,左侧用来显示播放音乐封面图,右侧用来进行音乐列表显示

  • 底部主要来显示当前播放音乐,播放进度条,音量控制,上一首/下一首,暂停/开始,播放方式等附加功能

关键字音乐列表爬虫

  • 通过输入的搜索关键字和选择的音乐来源,自动爬取对应的音乐数据

  • 将爬取获取的音乐名进行列表显示,显示在中间主体搜索页

音乐播放

  • 音乐列表中我们需要双击某一首歌,对爬取的歌曲封面图和歌曲进行下载

  • 下载成功,对音乐文件根据播放进度条进行播放

附加功能

  • 播放音乐时,我们还需要有播放暂停和启动功能

  • 音量控制提高或者降低

  • 当前播放歌曲上一首、下一首

  • 音乐列表播放方式,列表循环、单曲循环、随机播放

二、实现步骤

1. UI设计排版布局

基于功能点,我们首先考虑进行简单的UI布局设计,这里我们使用的是pyqt5。核心设计代码如下:

def init_ui(self):global typeself.setFixedSize(1025, 750)self.main_widget = QWidget()  # 创建窗口主部件self.main_layout = QGridLayout()  # 创建主部件的网格布局self.main_widget.setLayout(self.main_layout)  # 设置窗口主部件布局为网格布局self.close_widget = QWidget()  # 创建关闭侧部件self.close_widget.setObjectName('close_widget')self.close_layout = QGridLayout()  # 创建左侧部件的网格布局层self.close_widget.setLayout(self.close_layout)  # 设置左侧部件布局为网格self.left_widget = QWidget()  # 创建左边侧部件self.left_widget.setObjectName('left_widget')self.left_layout = QGridLayout()  # 创建左侧部件的网格布局层self.left_widget.setLayout(self.left_layout)  # 设置左侧部件布局为网格self.right_widget = QWidget()  # 创建右侧部件self.right_widget.setObjectName('right_widget')self.right_layout = QGridLayout()self.right_widget.setLayout(self.right_layout)  # 设置右侧部件布局为网格self.down_widget = QWidget()  # 创建下面部件self.down_widget.setObjectName('down_widget')self.down_layout = QGridLayout()self.down_widget.setLayout(self.down_layout)  # 设置下侧部件布局为网格self.up_widget = QWidget()  # 创建下面部件self.up_widget.setObjectName('up_widget')self.up_layout = QGridLayout()self.up_widget.setLayout(self.up_layout)  # 设置下侧部件布局为网格self.label = QLabel(self)self.label.setText("还没有播放歌曲呢╰(*°▽°*)╯")self.label.setStyleSheet("color:white")self.label.setMaximumSize(310, 20)self.main_layout.addWidget(self.up_widget, 0, 0, 1, 115)self.main_layout.addWidget(self.left_widget, 1, 0, 90, 25)self.main_layout.addWidget(self.right_widget, 1, 25, 90, 90)  # 22右侧部件在第0行第3列,占8行9列self.main_layout.addWidget(self.down_widget, 100, 0, 10, 115)self.main_layout.addWidget(self.close_widget, 0, 110, 1, 5)  # 左侧部件在第0行第0列,占1行3列self.down_layout.addWidget(self.label, 1, 0, 1, 1)self.setCentralWidget(self.main_widget)  # 设置窗口主部件self.tabWidget = QTabWidget(self)self.tabWidget.setGeometry(QRect(33, 20, 716, 471))self.tab = QWidget()self.tab.setObjectName("tab")self.tab_layout = QGridLayout()self.tab.setLayout(self.tab_layout)self.listwidget = QListWidget(self.tab)self.listwidget.doubleClicked.connect(lambda: self.change_func(self.listwidget))self.listwidget.setContextMenuPolicy(Qt.CustomContextMenu)self.listwidget.customContextMenuRequested[QPoint].connect(self.myListWidgetContext)self.listwidget.setObjectName("listWidget")self.tab_layout.addWidget(self.listwidget, 0, 0, 1, 1)self.tabWidget.addTab(self.tab, "      搜索页      ")self.tab2 = QWidget()self.tab2.setObjectName("tab")self.tab2_layout = QGridLayout()self.tab2.setLayout(self.tab2_layout)self.listwidget2 = QListWidget(self.tab2)self.listwidget2.doubleClicked.connect(lambda: self.change_funcse(self.listwidget2))self.listwidget2.setContextMenuPolicy(Qt.CustomContextMenu)self.listwidget2.customContextMenuRequested[QPoint].connect(self.myListWidgetContext2)self.listwidget2.setObjectName("listWidget2")self.listwidget2.setContextMenuPolicy(3)self.tab2_layout.addWidget(self.listwidget2, 0, 0, 1, 1)self.tabWidget.addTab(self.tab2, "      最近播放      ")self.right_layout.addWidget(self.tabWidget, 3, 0, 100, 90)self.left_close = QPushButton("")  # 关闭按钮self.left_close.clicked.connect(self.close)self.left_visit = QPushButton("")  # 空白按钮self.left_visit.clicked.connect(self.big)self.left_mini = QPushButton("")  # 最小化按钮self.left_mini.clicked.connect(self.mini)self.close_layout.addWidget(self.left_mini, 0, 0, 1, 1)self.close_layout.addWidget(self.left_close, 0, 2, 1, 1)self.close_layout.addWidget(self.left_visit, 0, 1, 1, 1)self.left_close.setFixedSize(15, 15)  # 设置关闭按钮的大小self.left_visit.setFixedSize(15, 15)  # 设置按钮大小self.left_mini.setFixedSize(15, 15)  # 设置最小化按钮大小self.left_close.setStyleSheet('''QPushButton{background:#F76677;border-radius:5px;}QPushButton:hover{background:red;}''')self.left_visit.setStyleSheet('''QPushButton{background:#F7D674;border-radius:5px;}QPushButton:hover{background:yellow;}''')self.left_mini.setStyleSheet('''QPushButton{background:#6DDF6D;border-radius:5px;}QPushButton:hover{background:green;}''')self.button_123 = QLabel("")self.left_layout.addWidget(self.button_123, 0, 2, 2, 2)self.label2 = QLabel(self)self.label2.setText("当前为顺序播放")self.label2.setStyleSheet("color:green")self.left_layout.addWidget(self.label2, 4, 0, 2, 1)self.button_1234 = QPushButton(icon('fa.download', color='#3FC89C', font=24), "")self.button_1234.clicked.connect(self.down)self.button_1234.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.left_layout.addWidget(self.button_1234, 4, 2, 2, 1)self.button_1234 = QPushButton(icon('fa.heart', color='#3FC89C', font=24), "")self.button_1234.clicked.connect(self.lovesong)self.button_1234.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.left_layout.addWidget(self.button_1234, 4, 3, 2, 2)self.label3 = QLabel(self)self.label3.setText("")self.label3.setStyleSheet("color:white")self.down_layout.addWidget(self.label3, 1, 3, 1, 1)self.label7 = QLabel(self)self.label7.setText("")self.label7.setStyleSheet("color:white")self.label5 = QLabel(self)pix_img = QPixmap(str(data + '/backdown.png'))pix = pix_img.scaled(300, 300, Qt.KeepAspectRatio)self.label5.setPixmap(pix)# self.label5.setMaximumSize(1,1)self.left_layout.addWidget(self.label5, 2, 0, 2, 8)self.label6 = QLabel(self)self.label6.setText("")self.label6.setStyleSheet("color:#6DDF6D")self.left_layout.addWidget(self.label6, 2, 0, 2, 2)self.label23 = QLabel(self)self.label23.setText("                 ")self.label23.setStyleSheet("color:#6DDF6D")self.up_layout.addWidget(self.label23, 0, 100, 1, 20)self.shuru = QLineEdit("")self.up_layout.addWidget(self.shuru, 0, 120, 1, 40)self.shuru.returnPressed.connect(self.correct)self.label23 = QLabel(self)self.label23.setText("     软件")self.label23.setStyleSheet("color:#6DDF6D")self.up_layout.addWidget(self.label23, 0, 160, 1, 10)self.label61 = QLabel(self)self.label61.setText("")self.label61.setStyleSheet("color:#6DDF6D")self.up_layout.addWidget(self.label61, 0, 200, 1, 50)self.cb = QComboBox(self)self.cb.addItems(['网易云', '酷狗',  'qq'])self.up_layout.addWidget(self.cb, 0, 180, 1, 30)self.cb.currentIndexChanged[int].connect(self.print)self.button_1 = QPushButton(icon('fa.search', color='white'), "")self.button_1.clicked.connect(self.correct)self.button_1.setStyleSheet('''QPushButton{color:white;border-radius:5px;}QPushButton:hover{background:green;}''')self.up_layout.addWidget(self.button_1, 0, 155, 1, 5)self.right_process_bar = QProgressBar()  # 播放进度部件self.right_process_bar.setValue(49)self.right_process_bar.setFixedHeight(3)  # 设置进度条高度self.right_process_bar.setTextVisible(False)  # 不显示进度条文字self.right_process_bar.setRange(0, 10000)self.right_playconsole_widget = QWidget()  # 播放控制部件self.right_playconsole_layout = QGridLayout()  # 播放控制部件网格布局层self.right_playconsole_widget.setLayout(self.right_playconsole_layout)self.console_button_1 = QPushButton(icon('fa.backward', color='#3FC89C'), "")self.console_button_1.clicked.connect(self.last)self.console_button_1.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.console_button_2 = QPushButton(icon('fa.forward', color='#3FC89C'), "")self.console_button_2.clicked.connect(self.nextion)self.console_button_2.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.console_button_3 = QPushButton(icon('fa.pause', color='#3FC89C', font=18), "")self.console_button_3.clicked.connect(self.pause)self.console_button_3.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.console_button_4 = QPushButton(icon('fa.volume-down', color='#3FC89C', font=18), "")self.console_button_4.clicked.connect(self.voicedown)self.console_button_4.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.console_button_5 = QPushButton(icon('fa.volume-up', color='#3FC89C', font=18), "")self.console_button_5.clicked.connect(self.voiceup)self.console_button_5.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.console_button_6 = QPushButton(icon('fa.align-center', color='#3FC89C', font=18), "")self.console_button_6.clicked.connect(self.playmode)self.console_button_6.setStyleSheet('''QPushButton{background:#222225;border-radius:5px;}QPushButton:hover{background:#3684C8;}''')self.console_button_3.setIconSize(QSize(30, 30))self.right_playconsole_layout.addWidget(self.console_button_4, 0, 0)self.right_playconsole_layout.addWidget(self.console_button_1, 0, 1)self.right_playconsole_layout.addWidget(self.console_button_3, 0, 2)self.right_playconsole_layout.addWidget(self.console_button_2, 0, 3)self.right_playconsole_layout.addWidget(self.console_button_5, 0, 4)self.right_playconsole_layout.addWidget(self.console_button_6, 0, 5)self.right_playconsole_layout.setAlignment(Qt.AlignCenter)  # 设置布局内部件居中显示self.down_layout.addWidget(self.right_process_bar, 0, 0, 1, 4)  # 第0行第0列,占8行3列# 第0行第0列,占8行3列self.down_layout.addWidget(self.label7, 1, 2, 1, 1)self.down_layout.addWidget(self.right_playconsole_widget, 1, 0, 1, 4)self.setWindowOpacity(0.95)  # 设置窗口透明度self.setAttribute(Qt.WA_TranslucentBackground)self.setWindowFlag(Qt.FramelessWindowHint)  # 隐藏边框self.main_layout.setSpacing(0)

实现效果如下:

2. 关键字音乐列表爬虫

我们可以根据输入的关键字和音乐来源进行音乐爬取。这里我们需要通过多线程,将歌曲、歌手、歌曲url地址全都获取。核心代码如下:

def run(self):qmut.lock()try:global paingglobal stopglobal lrcsglobal urlsglobal songsglobal nameglobal songidglobal proxiesglobal picglobal tryedpaing = Trueprint('搜索软件{}'.format(type))print('开始搜索')name = nameheaders = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.110.430.128 Safari/537.36','X-Requested-With': 'XMLHttpRequest'}urls = []songs = []pic = []lrcs = []pages = 5print(pages)for a in range(0, pages):if not stop:urlss = ['http://music.9q4.cn/', 'https://defcon.cn/dmusic/','http://www.xmsj.org/','http://music.laomao.me/']print (tryed)if tryed >3:tryed = 0url = urlss[tryed]else:url = urlss[tryed]print (urlss[tryed])params = {'input': name,'filter': 'name','type': type,'page': a}if not stop:try:res = post(url, params, headers=headers, proxies=proxies)html = res.json()for i in range(0, 10):try:title = jsonpath(html, '$..title')[i]author = jsonpath(html, '$..author')[i]url1 = jsonpath(html, '$..url')[i]  # 取下载网址pick = jsonpath(html, '$..pic')[i]  # 取歌词lrc = jsonpath(html, '$..lrc')[i]print(title, author)lrcs.append(lrc)urls.append(url1)pic.append(pick)songs.append(str(title) + ' - ' + str(author))except:passexcept:stop = Falsepaing = Falseself.trigger.emit(str('finish'))else:self.trigger.emit(str('finish'))else:self.trigger.emit(str('clear'))passstop = Falsepaing = Falseexcept:print('爬取歌曲出错')self.trigger.emit(str('unfinish'))stop = Falsepaing = Falseqmut.unlock()

爬取代码写好了,我们还需要将爬取的这些音乐数据列表显示到画面中搜索页面中。代码如下:

def repite(self, name, type):global tryedglobal paingglobal stopself.listwidget.clear()self.listwidget.addItem('搜索中')self.listwidget.item(0).setForeground(Qt.white)try:if paing:stop = Trueself.listwidget.clear()self.work2 = PAThread()self.work2.start()self.work2.trigger.connect(self.seafinish)else:self.work2 = PAThread()self.work2.start()self.work2.trigger.connect(self.seafinish)except:tryed = tryed + 1get_info('https://www.kuaidaili.com/free/inha')self.listwidget.addItem('貌似没网了呀`(*>﹏<*)′,再试一遍吧~')self.listwidget.item(0).setForeground(Qt.white)

效果如下:

3. 音乐播放

关键字搜索音乐列表完成之后,接下来我们需要实现音乐播放功能。首先需要从爬取的url下载待播放的歌曲,这里还是通过多线程进行。核心代码如下:

class WorkThread(QThread):trigger = pyqtSignal(str)def __int__(self):# 初始化函数super(WorkThread, self).__init__()# 进度条def cbk(self, a, b, c):'''''回调函数@a:已经下载的数据块@b:数据块的大小@c:远程文件的大小'''per = 100.0 * a * b / cif per > 100:per = 100# print   ('%.2f%%' % per)self.trigger.emit(str('%.2f%%' % per))def run(self):try:global numberglobal pathglobal downloadingtry:proxies = {'http': 'http://124.72.109.183:8118',' Shttp': 'http://49.85.1.79:31666'}headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36','X-Requested-With': 'XMLHttpRequest'}try:try:try:aq = pic[num]aqq = aq.split('/')except:passif type == 'kugou' and len(aqq) - 1 == 6:aqqe = str(aqq[0]) + str('//') + str(aqq[2]) + str('/') + str(aqq[3]) + str('/') + str('400') + str('/') + str(aqq[5]) + str('/') + str(aqq[6])print(aqqe)elif type == 'netease' and len(aqq) - 1 == 4:aqn = aq.split('?')b = '?param=500x500'aqqe = (str(aqn[0]) + str(b))print(aqqe)else:aqqe = pic[num]req = get(aqqe)checkfile = open(str(data + '/ls1.png'), 'w+b')for i in req.iter_content(100000):checkfile.write(i)checkfile.close()lsfile = str(data + '/ls1.png')safile = str(data + '/back.png')draw(lsfile, safile)except:passurl1 = urls[num]print(url1)number = number + 1path = str(data + '\{}.临时文件'.format(number))headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.110.430.128 Safari/537.36','X-Requested-With': 'XMLHttpRequest'}with get(url1, stream=True, headers=headers) as r, open(path, 'wb') as file:total_size = int(r.headers['content-length'])content_size = 0for content in r.iter_content(chunk_size=1024):file.write(content)content_size += len(content)plan = (content_size / total_size) * 100# print(int(plan))develop = str(int(plan)) + str('%')self.trigger.emit(str(develop))to = 'downloadmusic\{}.mp3'.format(songs[num])makedirs('downloadmusic', exist_ok=True)except:passtry:copyfile(path, to)except:passdownloading = Falseself.trigger.emit(str('finish'))except:self.trigger.emit(str('nofinish'))

音乐播放模块:

    def bofang(self, num, bo):print('尝试进行播放')try:import urllibglobal pauseglobal songsglobal musicglobal downloadingdownloading = Trueself.console_button_3.setIcon(icon('fa.pause', color='#F76677', font=18))pause = Falsetry:mixer.stop()except:passmixer.init()try:self.Timer = QTimer()self.Timer.start(500)except:passtry:self.label.setText('正在寻找文件...')self.work = WorkThread()self.work.start()self.work.trigger.connect(self.display)except:print('无法播放,歌曲下载错误')downloading = Falsepassexcept:sleep(0.1)print('播放系统错误')# self.next()passdef display(self, sd):global pauseglobal songedglobal urledglobal lrcdglobal timenumif sd == 'finish':try:if bo == 'boing':self.label.setText(songs[num])elif bo == 'boed':self.label.setText(songed[num])elif bo == 'love':self.label.setText(loves[num])try:pix_img = QPixmap(str(data + '/back.png'))pix = pix_img.scaled(300, 300, Qt.KeepAspectRatio)self.label5.setPixmap(pix)except:pix_img = QPixmap(str(data + '/backdown.png'))pix = pix_img.scaled(300, 300, Qt.KeepAspectRatio)self.label5.setPixmap(pix)print(str(data + '\{}.临时文件'.format(number)))mixer.music.load(str(data + '\{}.临时文件'.format(number)))  # 载入音乐mixer.music.play()self.console_button_3.setIcon(icon('fa.pause', color='#F76677', font=18))pause = Falsetry:mp3 = str(data + '\{}.临时文件'.format(number))xx = load(mp3)timenum = xx.info.time_secsglobal startstart = Trueexcept:print('MP3错误,播放失败')if bo == 'boing':songed.append(songs[num])urled.append(urls[num])picd.append(pic[num])lrcd.append(lrcs[num])r = 0self.listwidget2.clear()for i in songed:# self.listwidget.addItem(i)#将文件名添加到listWidgetself.listwidget2.addItem(i)self.listwidget2.item(r).setForeground(Qt.white)r = r + 1else:pass# 播放音乐except:passelif sd == 'nofinish':self.label.setText('下载错误')elif sd == 'lrcfinish':r = 0for i in lrct:if not i == '\r':r = r + 1else:passelif sd == 'lrcnofinish':passelse:self.label.setText('加速下载中,已完成{}'.format(sd))

至此,我们的音乐播放器已经可以正常播放音乐了。

4. 附加功能

主要功能已经完成了,下面我们还可以添加一些附加功能,例如播放方式列表循环、单曲循环、随机播放,当前上一首下一首播放,播放暂停开始,音量增加减少等等。

播放模式:

(1)随机播放:

def shui(self):global numglobal songsif bo == 'boing':q = int(len(songs) - 1)num = int(randint(1, q))elif bo == 'love':q = int(len(loves) - 1)num = int(randint(1, q))else:q = int(len(songed) - 1)num = int(randint(0, q))try:print('随机播放下一首')mixer.init()self.Timer = QTimer()self.Timer.start(500)# self.Timer.timeout.connect(self.timercontorl)#时间函数,与下面的进度条和时间显示有关if bo == 'boing':self.label.setText(songs[num])elif bo == 'love':self.label.setText(loves[num])else:self.label.setText(songed[num])self.bofang(num, bo)  # 播放音乐except:pass

(2) 上一首、下一首:

def last(self):global numglobal songsif num == 0:print('冇')num = len(songs) - 1else:num = num - 1try:self.bofang(num)self.label.setText(songs[num])except:pass#下一首
def next(self):print ('nexting')global numglobal songsif num == len(songs) - 1:print('冇')num = 0else:num = num + 1try:self.label.setText(songs[num])self.bofang(num)except:print ('next error')pass

(3)单曲循环:

def always(self):try:if bo == 'boing':self.label.setText(songs[num])else:self.label.setText(songed[num])self.bofang(num, bo)  # 播放音乐except:pass

(4) 播放模式选择:

def playmode(self):global playtry:if play == 'shun':play = 'shui'print('切换到随机播放')self.label2.setText("当前为随机播放")try:self.console_button_6.setIcon(icon('fa.random', color='#3FC89C', font=18))print('done')except:print('none')pass# self.left_shui.setText('切换为单曲循环')elif play == 'shui':play = 'always'print('切换到单曲循环')self.label2.setText("当前为单曲循环")try:self.console_button_6.setIcon(icon('fa.retweet', color='#3FC89C', font=18))print('done')except:print('none')# self.left_shui.setText('切换为顺序播放')elif play == 'always':play = 'shun'print('切换到顺序播放')self.label2.setText("当前为顺序播放")try:self.console_button_6.setIcon(icon('fa.align-center', color='#3FC89C', font=18))print('done')except:print('none')# self.left_shui.setText('切换为随机播放')except:print('模式选择错误')pass

播放暂停/开始:

def pause(self):global pauseif pause:try:mixer.music.unpause()except:passself.console_button_3.setIcon(icon('fa.pause', color='#3FC89C', font=18))pause = Falseelse:try:mixer.music.pause()except:passself.console_button_3.setIcon(icon('fa.play', color='#F76677', font=18))pause = True

音量提高/降低:

def voiceup(self):try:print('音量加大')global voicevoice += 0.1if voice > 1:voice = 1mixer.music.set_volume(voice)k = Decimal(voice).quantize(Decimal('0.00'))self.label3.setText('音量:{}'.format(str(k * 100) + '%'))except:passdef voicedown(self):try:print('音量减少')global voicevoice -= 0.1if voice < 0:voice = 0mixer.music.set_volume(voice)k = Decimal(voice).quantize(Decimal('0.00'))self.label3.setText('音量:{}'.format(str(k * 100) + '%'))except:pass

至此,这款音乐播放器就基本完成啦~ 一起来看看效果吧!

三、结束语

当然这款音乐播放器还有待完善的功能尚未完成:

  • 音乐本地下载保存

  • 播放本地音乐

  • 添加我喜爱的音乐功能

  • 歌词播放

  • 音乐进度跳播

后面有时间这些功能也会继续完善下!今天我们就到这里,明天继续努力!

左手Python,右手Java,升职就业不愁啦!

推荐阅读:入门: 最全的零基础学Python的问题  | 零基础学了8个月的Python  | 实战项目 |学Python就是这条捷径干货:爬取豆瓣短评,电影《后来的我们》 | 38年NBA最佳球员分析 |   从万众期待到口碑扑街!唐探3令人失望  | 笑看新倚天屠龙记 | 灯谜答题王 |用Python做个海量小姐姐素描图 |碟中谍这么火,我用机器学习做个迷你推荐系统电影趣味:弹球游戏  | 九宫格  | 漂亮的花 | 两百行Python《天天酷跑》游戏!AI: 会做诗的机器人 | 给图片上色 | 预测收入 | 碟中谍这么火,我用机器学习做个迷你推荐系统电影小工具: Pdf转Word,轻松搞定表格和水印! | 一键把html网页保存为pdf!|  再见PDF提取收费! | 用90行代码打造最强PDF转换器,word、PPT、excel、markdown、html一键转换 | 制作一款钉钉低价机票提示器! |60行代码做了一个语音壁纸切换器天天看小姐姐!|年度爆款文案1).卧槽!Pdf转Word用Python轻松搞定!2).学Python真香!我用100行代码做了个网站,帮人PS旅行图片,赚个鸡腿吃3).首播过亿,火爆全网,我分析了《乘风破浪的姐姐》,发现了这些秘密 4).80行代码!用Python做一个哆来A梦分身 5).你必须掌握的20个python代码,短小精悍,用处无穷 6).30个Python奇淫技巧集 7).我总结的80页《菜鸟学Python精选干货.pdf》,都是干货 8).再见Python!我要学Go了!2500字深度分析!9).发现一个舔狗福利!这个Python爬虫神器太爽了,自动下载妹子图片点阅读原文,领AI全套资料

http://www.ppmy.cn/news/306562.html

相关文章

推荐9个鲜为人知的Python第三方库

Python 编程充满了机会。它简单明了&#xff0c;拥有许多很酷的库和特色功能&#xff0c;可以使任务变得简单得多。每个 Python 开发人员都必须与热门的第三方库合作&#xff0c;如 NumPy、pandas、datetime等。然而&#xff0c;有一些鲜为人知的第三方库&#xff0c;可以让作为…

华为天才少年造出自动驾驶单车!图纸已开源,硬件成本一万!

鱼羊 金磊 发自 凹非寺 量子位 报道 | 公众号 QbitAI 果然高手在民间。 谁能料到&#xff0c;一辆自行车的硬核打开方式&#xff0c;竟是大火的自动驾驶。 踢开脚撑&#xff0c;金鸡独立、稳如泰山&#xff1a; 单侧加个板砖&#xff1f;小场面&#xff1a; 毕竟&#xff0c;它…

推荐5个超级实用的 Python 模块,不知道就out啦!

点击上方“菜鸟学Python”&#xff0c;选择“星标”公众号 超级无敌干货&#xff0c;第一时间送达&#xff01;&#xff01;&#xff01; 编辑&#xff1a;乐乐 | 来自&#xff1a;网络 正文 大家好&#xff0c;我是菜鸟哥。 Python 标准库有超过 200 个模块&#xff0c;程序员…

用 Python 写个贪吃蛇,保姆级教程!

本文基于 Windows 环境开发&#xff0c;适合 Python 新手 项目地址&#xff1a;https://github.com/AnthonySun256/easy_games 下面我们就一起用 Python 实现一个简单有趣的命令行贪吃蛇小游戏&#xff0c;启动命令&#xff1a; git clone https://github.com/AnthonySun256/ea…

12个必备的Python函数,新手看完就入门啦!

来源&#xff1a;https://sslljy.blog.csdn.net/?typeblog 前言 大家好&#xff0c;我是菜鸟哥。 新手在做写代码的时候容易卡壳&#xff0c;尤其当接触的函数以及其他知识比较多的时候&#xff0c;经常会看完需求之后不知道自己该用什么方法来实现它&#xff0c;实现的逻辑可…

微软出Django教程啦!

周围很多小伙伴都在学Python。Python功能强大&#xff0c;语法简单&#xff0c;可以干很多事情。比如自动化测试&#xff0c;运维&#xff0c;机器学习&#xff0c;数据分析&#xff0c;金融股票量化分析&#xff0c;其实很多小公司或者大厂的运维部门都用Python做Web后台开发的…

游戏分类的英文缩写与全写

RPG Role-playing Game∶角色扮演游戏 由玩家扮演游戏中的一个或数个角色&#xff0c;有完整的故事情节的游戏。玩家可能会与冒险类游戏混淆&#xff0c;其实区分很简单&#xff0c;RPG游戏更强调的是剧情发展和个人体验&#xff0c;一般来说&#xff0c;RPG可分为日式和美式两…

旧梦。

那些短暂的相遇,短暂的美好&#xff0c;会不会在心里埋下长久的种子 D2019-9 30号 早上老徐来班里外出前洗脑。开头第一句"今天我们大部分同学都外出培训"。(没关系我习惯了&#xff0c;信息不占比例。。) "我们的目标是每科一个金牌"..... (想peach)。 &q…