前言晚上坐在电脑面前,想着一边撸代码,一边听音乐。搜了搜自己想听的歌,奈何好多歌曲都提示需要版权,无法播放! 没办法,想听歌还是得靠自己解决!今天就一起用python自制一款炫酷的音乐播放器吧~ 首先一起来看看最终实现的音乐播放器效果:
一、核心功能设计总体来说,我们首先需要设计UI界面,对播放器的画面布局进行排版设计;其次我们的这款音乐播放器的主要功能包括根据关键字搜索自动爬取音乐,获取音乐列表,能进行音乐播放。 当然还少不了一些附加功能,例如播放方式列表循环、单曲循环、随机播放,当前上一首下一首播放,播放暂停开始,音量增加减少,播放历史查看等。 拆解需求,大致可以整理出核心功能如下: UI设计排版布局
关键字音乐列表爬虫
音乐播放
附加功能
二、实现步骤1. UI设计排版布局基于功能点,我们首先考虑进行简单的UI布局设计,这里我们使用的是pyqt5。核心设计代码如下: def init_ui(self): global type self.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 repite(self, name, type): global tryed global paing global stop self.listwidget.clear() self.listwidget.addItem('搜索中') self.listwidget.item(0).setForeground(Qt.white) try: if paing: stop = True
self.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 + 1 get_info('https://www./free/inha') self.listwidget.addItem('貌似没网了呀`(*>﹏<*)′,再试一遍吧~') self.listwidget.item(0).setForeground(Qt.white) 效果如下: 3. 音乐播放关键字搜索音乐列表完成之后,接下来我们需要实现音乐播放功能。首先需要从爬取的url下载待播放的歌曲,这里还是通过多线程进行。核心代码如下:
音乐播放模块: def bofang(self, num, bo): print('尝试进行播放') try: import urllib global pause global songs global music global downloading downloading = True self.console_button_3.setIcon(icon('fa.pause', color='#F76677', font=18)) pause = False try: mixer.stop() except: pass mixer.init() try: self.Timer = QTimer() self.Timer.start(500) except: pass try: self.label.setText('正在寻找文件...') self.work = WorkThread() self.work.start() self.work.trigger.connect(self.display) except: print('无法播放,歌曲下载错误') downloading = False pass except: sleep(0.1) print('播放系统错误') # self.next() pass
def display(self, sd): global pause global songed global urled global lrcd global timenum if 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 = False try: mp3 = str(data + '\{}.临时文件'.format(number)) xx = load(mp3) timenum = xx.info.time_secs global start start = True except: print('MP3错误,播放失败')
if bo == 'boing': songed.append(songs[num]) urled.append(urls[num]) picd.append(pic[num]) lrcd.append(lrcs[num]) r = 0 self.listwidget2.clear() for i in songed: # self.listwidget.addItem(i)#将文件名添加到listWidget
self.listwidget2.addItem(i) self.listwidget2.item(r).setForeground(Qt.white) r = r + 1 else: pass # 播放音乐 except: pass elif sd == 'nofinish': self.label.setText('下载错误') elif sd == 'lrcfinish': r = 0 for i in lrct: if not i == '\r': r = r + 1 else: pass elif sd == 'lrcnofinish': pass else: self.label.setText('加速下载中,已完成{}'.format(sd)) 至此,我们的音乐播放器已经可以正常播放音乐了。 4. 附加功能主要功能已经完成了,下面我们还可以添加一些附加功能,例如播放方式列表循环、单曲循环、随机播放,当前上一首下一首播放,播放暂停开始,音量增加减少等等。 播放模式: (1)随机播放:
(2) 上一首、下一首: def last(self): global num global songs if num == 0: print('冇') num = len(songs) - 1 else: num = num - 1 try: self.bofang(num) self.label.setText(songs[num]) except: pass
#下一首 def next(self): print ('nexting') global num global songs if num == len(songs) - 1: print('冇') num = 0 else: num = num + 1 try: self.label.setText(songs[num]) self.bofang(num) except: print ('next error') pass (3)单曲循环:
(4) 播放模式选择: def playmode(self): global play try: 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 voiceup(self): try: print('音量加大') global voice voice += 0.1 if voice > 1: voice = 1 mixer.music.set_volume(voice) k = Decimal(voice).quantize(Decimal('0.00')) self.label3.setText('音量:{}'.format(str(k * 100) + '%')) except: pass
def voicedown(self): try: print('音量减少') global voice voice -= 0.1 if voice < 0: voice = 0 mixer.music.set_volume(voice) k = Decimal(voice).quantize(Decimal('0.00')) self.label3.setText('音量:{}'.format(str(k * 100) + '%')) except: pass 至此,这款音乐播放器就基本完成啦~ 一起来看看效果吧! 时长 00:57 三、结束语当然这款音乐播放器还有待完善的功能尚未完成:
后面有时间这些功能也会继续完善下!今天我们就到这里,明天继续努力! 本文链接:https://blog.csdn.net/hhladminhhl/article/details/118915410 文章转载:Python编程学习圈
|
|
来自: 我本无我O > 《Python 知识》