PyQt5实战——本地音乐播放器

目录

目录

效果图如下:

写在前面: 

第一个难点——滑块转换

第二个难点——页面的布局

top_widget

left_widget

right_widget

right_widget_popular——华语流行 对应的界面主控件

right_widget_FM——在线FM 对应的界面的主控件

right_widget_MV——热门MV 对应的界面的主控件

right_widget_local——本地音乐 对应的界面的主控件

right_widget_download——下载管理 对应的界面的主控件

right_widget_like——我的收藏 对应的界面的主控件

right_widget_suggest——反馈建议 对应的界面的主控件

right_widget_star——关注我们 对应的界面的主控件

right_widget_question——遇到问题 对应的界面的主控件

bottom_widget

第三个难点——布局中的按钮的各种功能实现

第四个难点——美化界面

写在最后:


效果图如下:

写在前面: 

开发环境如下:

Python 3.9.12
conda 22.9.0(pyqt5包含在anaconda里面)
QtAwesome   1.0.3
mutagen   1.47.0

项目gitee地址:PyQt: 本地音乐播放器 (gitee.com)

第一个难点——滑块转换

单独使用music_move_hua.py这样一个文件来完成。

思路:

  •     总控件是一个无边框的QWidget,通过
    self.setWindowFlag(QtCore.Qt.FramelessWindowHint)设置
  • 总布局是一个水平布局,在最左边放向左滑动的按钮,在最右边放向右滑动的按钮。同时设置按钮的样式,进行小小的美化工作。
  • 在这里,QLabel(内容是gif)我是根据总控件的大小来设置其绝对位置的,这里曾尝试将label放入布局中,但这样无法实现label之间有重叠,于是才采用这种使用绝对布局方法。代码里面设置的x和y坐标仅供参考,主要目的还是实现Qlabel的居中效果。
  • 最后就是设置向左按钮和向右按钮的点击事件,从而实现滑动效果。 

这里以向左按钮的点击事件为例:

  • 首先,在代码里面写了一个QLabel的子类mylabel,增加两个属性——cur_left_Index和cur_right_Index,这两个属性负责记录label当前处于的index,从而决定下一步如何处理该label。要认清一点,是根据Index来识别label,从而决定处理
  • 下图是第一次按下向左滑动的按钮的显示图片:

  • 在初始化的时候,我们让label0放在中间,它的初始cur_left_Index=0;左边是label3,它的初始cur_left_Index=3;右边是label1,它的初始cur_left_Index=1;而label2其实也在中间,只是它的大小要比label0要小,同时我们也将label0置于最顶层了,所以实现了label2的不可见,label2的初始cur_left_Index=2;
  • 现在进行第一次按下向左滑动按钮事件:现在label1在中间,它的cur_left_Index=0;label0在左边,它的cur_left_Index=3;label2在右边,它的cur_left_Index=1;label3现在在中间,它的cur_left_Index=2,同时将其透明度设为0,实现其不可见。
  • 从上面的一次移动事件,我们可以得出规律:如果当前label的cur_left_Index=0,说明他现在在中间,那么该次处理就应该将其移动到左边了,同时将该label的cur_left_Index设置为3;同理,当前label的cur_left_Index=3,我们需要先将其透明度设置为0,然后将其移动到中间,再将其cur_left_Index设置为2;而当label的cur_left_Index=2的时候,我们首先要将label的透明度设置为1,将label设置为可见,将其移动到右边,然后将其cur_left_Index设置为1;其他的同理;

向右滑动的按钮的点击事件也同理。但是当你分别设置完两个按钮的点击事件后,突然发现,在实际的应用场景中,我们不可能一直只点向右滑动,或者向左滑动,更多时候是交替点击的,所以这个时候,我们就需要在点击事件里面增加代码,分别设置在左按钮点击后,label的cur_right_Index值;在点击右按钮后,设置label的cur_left_Index的值,下面以一次向右移动后的事件为例讲解:

  • 由图可知,在向右点击后,我们的label0移动到了右边,cur_right_Index从0变成1。那么在右边的label,如果我们想向左边移动的时候,我们右边的cur_left_Index应该是多少呢?答案很明显,右边label的cur_left_Index此时应该为1;所以我们就得出了结果——当label的cur_right_Index从0变为1的时候,我们此时也应该将cur_left_Index设置为1,从而下次无论是向左移动还是向右移动,我们都能从容应对。
  • 同理,我们在按钮点击事件的所有情况都分析一遍,无论向左还是向右移动,我们都同时设置cur_left_Index和cur_right_Index,这样我们就可以随意点击向左和向右按钮了。

第二个难点——页面的布局

下图是页面的总布局:

  • 首先总控件仍然是一个QWidget,main_widget 仍然是无边框的。
  • main_widget的布局时网格布局,如上图所示,里面放置着top_widget、left_widget、right_widget、bottom_widget。
top_widget
  • top_widget的布局时水平垂直布局,里面放置的控件如下图所示:

  • 最左边的Qlabel放置一个动态的gif图片,第二个Qlabel设置文本为“搜索:”,第三个就是文本输入框,后面三个QPushButton分别是最小化按钮,最大化按钮,关闭按钮。
  • 为了实现三个按钮的功能,需要自行设置按钮对应的点击事件。
  • 最小化按钮对应的函数self.showMinimized是自带的函数,不需要我们进行实现。
  • 最大化按钮对应的函数需要我们不仅能够实现最大化,还需要能够从最大化的状态回到正常状态,所以需要我们进行一个判断,判断当前是否处于最大化状态,然后再利用自带的函数实现功能。
  • 关闭按钮对应的函数也是自带的函数,不需要我们实现。
  • 然后就是分别对布局里边的各个控件通过css进行美化。 
left_widget

  • left_widget的布局是一个网格布局,里面全是QPushButton,然后通过给QPushButton设置不同的ObjectName,利用ObjectName再设置样式的时候进行区分。 
right_widget

        right_widget其实是一个QStackedWidget,也就是一个堆栈窗口控件。里面存放着不同的界面,然后通过left_widget的按钮触发事件,从而显示不同的界面。

right_widget_popular——华语流行 对应的界面主控件

  • right_widget_popular的布局是垂直布局,它里面的控件是hua_scrollbar(QScrollArea类型);而hua_scrollbar里面的控件是right_widget_hua,right_widget_hua的布局是网格布局,里面有四个控件——hua_recommend_label、hua_recommed_widget、hua_palylist_lable、hua_palylist_widget。
  • hua_recommend_label:里面放置的控件是QLabel,文本设置为“今日推荐”。
  • hua_recommend_widget:里面放置的控件是前文提到的移动窗口实例。
  • hua_palylist_lable:里面放置的控件时QLabel,文本设置为“推荐歌单”。
  • hua_palylist_widget:它的布局是网格布局,里面放置的样式和图中一样,每个QtoolButton的下面放置一个Qlabel,一列放置五个QToolButton。
  • 由于hua_scrollbar是QScrollArea类型,所以该控件是自带滚动条的,而我们只需要纵向的滚动条,所以需要手动将横向的滚动条隐藏掉。
right_widget_FM——在线FM 对应的界面的主控件

  • right_widget_FM的布局是网格布局,里面放置着三个Qlabel。
  •  第一个QLabel的文本是“什么?你还不知道这个网站,点击下方连接获得同款喔!”
  • 第二个QLabel里面放置的是一个gif动图——向日葵。
  • 第三个QLabel的文本是一个超链接,文本内容是“一个音乐网站”。
right_widget_MV——热门MV 对应的界面的主控件

  • right_widget_MV的布局是网格布局,里面同样放置着三个QLabel。
  • 左上角的QLabel放置着一个猫爪的gif动图。
  •  右上角的QLabel的文本内容是“该页面正在骑马来的路上!!!”。
  • 下面的QLabel的内容是一个加载的gif动图。
right_widget_local——本地音乐 对应的界面的主控件

  •  right_widget_local的布局是网格布局,里面放置着两个控件——local_songs_widget、local_add_songs_widget。
  • local_songs_widget:该控件是QTableView类型,标题行是“标题,歌手,时长”
  • local_add_songs_widget:该控件的布局是水平布局,里面有三个QPushButton,第一个按钮是文本是“添加歌曲”,第二个按钮的文本是“添加文件夹”,第三个按钮的文本是“删除所有歌曲”。
  • 添加歌曲功能:利用QFileDialog的getOpenFileName方法,打开文件夹,选取其中的MP3文件,返回值是文件的绝对路径,然后调用add_song_from_path函数。
  • 添加文件夹功能:利用QFileDialog的getExistingDirectory方法,选取文件夹,返回文件夹的绝对路径。然后调用getFiles函数,获取文件夹下面的所有.mp3文件名。然后将文件夹的绝对路径和文件名拼接在一块,形成文件的绝对路径,调用add_song_from_path函数。
  • add_song_from_path函数:参数是path,要添加文件的绝对路径;首先我们判断该路径是否存在于media_list里面,如果存在,弹出信息框,表明歌曲已经存在于歌单中;如果不存在,则将path加入media_list中,利用MP3方法算出歌曲的时长、然后将path写入到文件songs.txt中(这样就能实现永久性添加歌曲,每次运行的时候,media_list都会从songs.txt读取数据);接着在播放列表play_list和QTableView数据源model中分别添加歌曲。
  • 删除单首歌曲:这个功能是通过右击歌曲,弹出一个上下文菜单,点击“删除当前选中的歌曲”实现。 删除歌曲的时候,不仅要在media_list中删除,还要删除media_duration中删除对应项,在播放列表play_list和QTableView数据源model中删除,最后还要将删除该歌曲信息后的media_list重新写入文件songs.txt,从而实现永久性删除。
  • 删除所有歌曲功能:首先弹出对话框,确认是否要删除所有歌曲。如果点解Yes,那就直接清空播放列表、QTableView数据源model、文件songs.txt、media_list、media_duartion。
right_widget_download——下载管理 对应的界面的主控件

该页面实现与热门MV相同

right_widget_like——我的收藏 对应的界面的主控件

该页面实现与热门MV相同

right_widget_suggest——反馈建议 对应的界面的主控件

  • 布局仍然使用的是网格布局,里面放置着四个QLabel。
  • 左上角的QLabel的文本内容是“什么?你想支持作者?太感动辣!!!!”。
  • 右上角的QLabel的内容是一个 委屈的gif动图。
  • 中间的QLabel的内容是一个图片。
  • 右下角的QLabel的文本是一个超链接,文本内容是“快v我50”。 
right_widget_star——关注我们 对应的界面的主控件

该页面实现与反馈建议相同

right_widget_question——遇到问题 对应的界面的主控件

该页面实现与反馈建议相同

bottom_widget

  •  布局仍然是网格布局,里面放置三个Qwidget——bottom_music_widget、bottom_playconsole_widget、bottom_right_widget。
  • bottom_music_widget:布局仍是网格布局,左边的QLabel内容是一张图片,右上角的QLabel的文本内容是歌曲名,右下角的QLabel的文本内容是歌手名,需要注意的一点是,只有播放歌曲后,这两个标签才会有内容,不然文本是空的。
  • bottom_playconsole_widget:网格布局,上面三个按钮分别是上一首,暂停,下一首。下面的QSlider是歌曲播放进度条,右侧的Qlabel是显示歌曲剩余时间。
  • bottom_right_widget:水平布局,第一个按钮是不同的播放模式,第二个按钮是音量键,第三个按钮是音量滑条。
  • 底部控件实现的功能有:可以通过滑动进度条改变歌曲播放进度;按下下一首或上一首从而切换歌曲;按下暂停按钮,实现歌曲暂停或播放功能;按下播放模式按钮,切换播放模式;按下音量键按钮,设置为静音或正常音量;滑动音量条,改变音量大小。

第三个难点——布局中的按钮的各种功能实现

由于篇幅原因,这里不再赘述,下面是代码中关于按钮和响应事件连接的函数,可以通过这个联系来查找相关功能函数。

    def signal_init(self):
        """添加按钮响应事件"""
        self.left_button_1.clicked.connect(lambda: self.right_widget.setCurrentIndex(0))
        self.left_button_2.clicked.connect(lambda: self.right_widget.setCurrentIndex(1))
        self.left_button_3.clicked.connect(lambda: self.right_widget.setCurrentIndex(2))
        self.left_button_4.clicked.connect(lambda: self.right_widget.setCurrentIndex(3))
        self.left_button_5.clicked.connect(lambda: self.right_widget.setCurrentIndex(2))
        self.left_button_6.clicked.connect(lambda: self.right_widget.setCurrentIndex(2))
        self.left_button_7.clicked.connect(lambda: self.right_widget.setCurrentIndex(6))
        self.left_button_8.clicked.connect(lambda: self.right_widget.setCurrentIndex(6))
        self.left_button_9.clicked.connect(lambda: self.right_widget.setCurrentIndex(6))


        # todo 添加底部按钮响应时间
        self.bottom_sound_btn.clicked.connect(lambda: self.btn_func(self.bottom_sound_btn))
        self.bottom_console_button_1.clicked.connect(lambda: self.btn_func(self.bottom_console_button_1))
        self.bottom_console_button_3.clicked.connect(lambda: self.btn_func(self.bottom_console_button_3))
        self.bottom_console_button_2.clicked.connect(lambda: self.btn_func(self.bottom_console_button_2))
        self.bottom_mode_btn.clicked.connect(lambda: self.btn_func(self.bottom_mode_btn))
        # self.list_btn.clicked.connect(lambda: self.btn_func(self.list_btn))
        #
        self.bottom_volume_slider.valueChanged.connect(self.volume_slider_func)
        self.local_songs_widget.doubleClicked.connect(self.table_play_func)
        # 分别利用durationChanged来监听获取时长,positionChanged信号会在当前播放时长(position)改变的时候发射
        self.player.durationChanged.connect(self.get_duration_func)
        self.player.positionChanged.connect(self.get_position_func)
        # todo 通过手动改变滑动条改变播放进度,而sliderMoved之歌信号只有在用户手动改变滑动条值的情况下才会发射
        self.bottom_process_bar.sliderMoved.connect(self.update_position_func)
        # 如果播放列表中的正在播放的歌曲播放完,然后改变,那对应的播放按钮应该改成pause的形状
        self.play_list.currentIndexChanged.connect(self.update_console_btn_func)

        # 打开文件格式(*.mp3)文件,添加到播放列表中
        self.local_add_song_btn.clicked.connect(self.add_song)
        # 选择文件夹并打开,然后添加文件夹下面的歌曲
        self.local_add_dic_btn.clicked.connect(self.add_dic)
        # 当播放列表中单元格被右键点击的时候,弹出上下文菜单用以删除歌曲
        self.local_songs_widget.customContextMenuRequested.connect(self.generateMenu)
        # 删除所有歌曲按钮点击事件
        self.local_del_songs_btn.clicked.connect(self.del_all_songs)

第四个难点——美化界面

这个部分是在网上不断找相关资料堆砌出来的。一些资料链接放在下面了。

左侧控件和背景美化:实战!在Python中制作精美的图形用户界面 - 知乎 (zhihu.com)

搜索框(QLineEdit)美化:[PYQT5]如何做出精美界面,让你的软件高n个档次,QSS实例教程--不定时更新--part1[QLineEdit]_pyqt5开发的漂亮界面-CSDN博客 

滑动条美化(QSlider):【QSlider样式表的详细设置及含义】_神迷岛的博客-CSDN博客 

按钮(QPushButton)美化:Qt: QPushButton 常见样式设置_qpushbutton样式_not so perfect的博客-CSDN博客

除了这些,还有一些美化代码出处没有进行记录,大家可以搜索一下相关控件的美化。

写在最后:

        写这个播放器的出发点是想将学习的PyQt5的知识进行一个小的融合,刚开始只是按照上面提供的第一个链接的界面去写的,但写的过程感觉这个界面只是一个界面,没有一点灵动的东西。于是就添加了一个可以左右滑动的窗口。然后又觉得只写一个界面太简单了,就想多写几个界面,最后左思右想,就想出了多写一个本地音乐播放的界面,这样这个界面不至于一点功能没有。最后经过几天的努力,有了这样一个程序。

        这个博客里面重点写了整个页面的布局,以及移动窗口的实现,相关功能的实现并没有进行太多介绍,这里当然那不会说是因为本人懒哈。 

        当然,由于本人代码能力有限,而且开发经验欠缺,只有两个代码文件,显得有些冗长和杂乱,望见谅。

        还有一点要注意:

                如果你想要在歌手栏出现歌手名字,那么你的MP3文件名要改成"歌曲名_歌手名"的格式,如果只有歌曲名,那么歌手栏会自动填充未知歌手,下面是一个例子截图:

导入后的效果如下:

        

        下面是主代码:

# 类音乐软件界面UI设计
"""最大化的时候移动窗口控件有问题,暂时没有想到解决方案-9.19"""

"""待写-》 9.22
1. 添加文件夹功能 ok
2. 添加mp3后,mp3不能播放 提示错误信息 ok
3. 两个添加按钮美化  ok
4. 滑动条美化  ok
5. 删除歌曲按钮  ok
6. 显示当前播放的歌曲名、歌手  ok
7. 歌单中没有歌曲的时候,处理点击播放按钮事件  ok 
8. 如果添加歌曲或文件夹的时候,点取消,那就直接pass  ok
9. 美化弹出的窗口  to bo continued
"""
"""歌单控件使用Qtoolbutton,还没有设置圆角"""
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
from PyQt5.QtWidgets import QFileDialog, QMessageBox
from PyQt5.QtNetwork import QNetworkProxyFactory
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent, QMediaPlaylist
# 通过该库来获取歌曲时长
from mutagen.mp3 import MP3
import sys
import os
# 可以通过该库设置图标
import qtawesome
from music_move_hua import *



class MainUi(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainUi, self).__init__()
        # 设置窗口无边框
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
        self.initUI()

    def initUI(self):
        '''
        设置主界面
        :return:
        '''
        self.resize(1280, 700)
        self.hua_recommend_widget_width = int(self.width()*0.6)
        self.hua_recommend_widget_height = int(self.height()*0.4)

        # 设置鼠标位置
        self._startPos = None
        self._endPos = None
        self._isTracking = None

        self.main_widget = QtWidgets.QWidget()  # 创建窗口主部件
        self.main_layout = QtWidgets.QGridLayout()  # 创建主部件的网格布局
        self.main_widget.setLayout(self.main_layout)    # 设置窗口主部件布局为网格布局

        self.left_widget = QtWidgets.QWidget()  # 创建左侧部件
        self.left_widget.setObjectName('left_widget')
        self.left_layout = QtWidgets.QGridLayout()  # 左侧布局为网格布局
        self.left_widget.setLayout(self.left_layout)

        self.right_widget_popular = QtWidgets.QWidget()# todo 创建  华语流行对应的界面
        self.rigth_widget_hua = QtWidgets.QWidget()  # todo 创建  华语流行中 滚动区域 对应的控件
        # self.right_widget_FM = QtWidgets.QWidget()  # todo 创建 在线FM 对应的界面
        self.right_widget_FM = QWidget()
        self.right_widget_MV = QtWidgets.QWidget()  # todo 创建 热门MV 对应的界面
        self.right_widget_local = QtWidgets.QWidget()   # todo 创建 本地音乐 对应的界面
        self.right_widget_download = QtWidgets.QWidget()    # todo 创建 下载管理 对应的界面
        self.right_widget_like = QtWidgets.QWidget()    # todo 创建 我的收藏 对应的界面
        self.right_widget_suggest = QtWidgets.QWidget() # todo 创建 反馈建议 对应的界面
        self.right_widget_star = QtWidgets.QWidget()    # todo 创建 关注我们 对应的界面
        self.right_widget_question = QtWidgets.QWidget()    # todo 创建 遇到问题 对应的界面

        self.right_widget = QtWidgets.QStackedWidget()      # todo 创建右侧 堆栈窗口控件
        self.right_widget.addWidget(self.right_widget_popular)
        self.right_widget.addWidget(self.right_widget_FM)
        self.right_widget.addWidget(self.right_widget_MV)
        self.right_widget.addWidget(self.right_widget_local)
        self.right_widget.addWidget(self.right_widget_download)
        self.right_widget.addWidget(self.right_widget_like)
        self.right_widget.addWidget(self.right_widget_suggest)
        self.right_widget.addWidget(self.right_widget_star)
        self.right_widget.addWidget(self.right_widget_question)

        # 创建顶部布局实例
        self.top_widget = QtWidgets.QWidget()
        self.top_widget.setObjectName("top_widget") # 当鼠标处于顶部布局时,才能移动窗口
        self.top_layout = QHBoxLayout()
        self.top_widget.setLayout(self.top_layout)

        # 在工具栏里面添加搜索框 和左侧动图
        self.music_icon = QtWidgets.QLabel()
        self.movie = QMovie('./images/用手比枪砰.gif')
        self.music_icon.setMovie(self.movie)
        self.movie.start()
        self.music_icon.setFixedSize(80, 60)
        self.music_icon.setScaledContents(True)
        # 设置搜索框
        self.search_icon = QtWidgets.QLabel(chr(0xf002) + '' + '搜索: ')
        self.search_icon.setFont(qtawesome.font('fa', 16))
        self.search_input = QtWidgets.QLineEdit()
        self.search_input.setObjectName('search_input')
        self.search_input.setPlaceholderText('输入歌手、歌曲或用户,回车进行搜索')
        # 设置最大化,最小化,关闭按钮
        self.max_btn = QtWidgets.QPushButton(qtawesome.icon('fa.window-maximize', color='#FFB6C1'), '')
        self.close_btn = QtWidgets.QPushButton(QtGui.QIcon('./images/x.png'), '')
        self.min_btn = QtWidgets.QPushButton(qtawesome.icon('fa.minus', color='#FFB6C1'), '')
        # 设置按钮对应的槽函数
        # 系统自带的最小化函数
        self.min_btn.clicked.connect(self.showMinimized)
        # 不仅要能够最大化,还要在最大化的时候按下能够回到正常
        self.max_btn.clicked.connect(self.maxOrNormal)
        # 关闭的时候弹出窗口询问是否关闭
        self.close_btn.clicked.connect(self.close)

        # 工具栏中添加控件
        self.top_layout.addWidget(self.music_icon)
        self.top_layout.addWidget(self.search_icon)
        self.top_layout.addWidget(self.search_input)
        self.top_layout.addWidget(self.min_btn)
        self.top_layout.addWidget(self.max_btn)
        self.top_layout.addWidget(self.close_btn)


        # 创建底部控件,里面放进度条
        self.bottom_widget = QtWidgets.QWidget()
        # self.bottom_widget.setFixedSize(self.width(), int(self.height()-self.top_widget.height()-self.right_widget_popular.height()))
        self.bottom_layout = QtWidgets.QGridLayout()
        self.bottom_widget.setLayout(self.bottom_layout)

        # 实例化音乐媒体控件
        self.player = QMediaPlayer()
        self.play_list = QMediaPlaylist()
        self.init_play()

        self.main_layout.addWidget(self.top_widget, 0, 0, 1, 12)
        self.main_layout.addWidget(self.left_widget, 1, 0, 11, 2)   # 左侧部件在第0行第0列,占12行2列
        self.main_layout.addWidget(self.right_widget, 1, 2, 11, 10)
        self.main_layout.addWidget(self.bottom_widget, 12, 0, 2, 12)

        # 添加左部控件
        self.add_left_widgets()
        # 添加底部控件
        self.add_bottom_widgets()
        # 设置UI
        self.UI_hua()
        self.UI_local()
        self.UI_FM()
        self.UI_MV()
        self.UI_suggest()
        # 设置信号响应
        self.signal_init()


        # 美化UI
        self.pretty_UI()

        self.setCentralWidget(self.main_widget)     # 设置窗口主部件

    def maxOrNormal(self):
        '''
        设置最大化按钮的功能,切换最大化与正常大小
        :return:
        '''
        if self.isMaximized():
            # self.hua_recommend_widget.resize(int(1171*0.9), int(700*0.4))
            self.showNormal()
            # self.hua_recommend_widget.resize(int(1171*0.9), int(700*0.4))
        else:
            # self.hua_recommend_widget.resize(int(1920*0.9), int(1020*0.4))
            self.showMaximized()
            # self.hua_recommend_widget.resize(int(1920*0.9), int(1020*0.4))



    def init_play(self):
        '''
        实例化媒体控件
        :return:
        '''
        self.player.setPlaylist(self.play_list)

        with open('songs.txt', 'r', encoding='utf-8') as f:
            self.media_list = [m for m in f.read().split('\n')]
        # 存放歌曲长度
        # 如果文件为空,那将写入列表的一个空字符串删除
        if self.media_list[0] == '':
            self.media_list.pop(0)

        self.media_duration = []
        for m in self.media_list:
            try:
                duration = MP3(m).info.length
                minutes = int(duration/60)
                seconds = int(duration-minutes*60)
                self.media_duration.append('{}:{}'.format(minutes, seconds))
                self.play_list.addMedia(QMediaContent(QUrl.fromLocalFile(m)))
            except:
                song_name = m.split('/')[-1]
                QMessageBox.information(self, '提示', '歌曲 {} 格式暂不支持播放'.format(song_name), QMessageBox.Yes)

        # 设置初始播放模式为随机播放
        self.play_list.setPlaybackMode(QMediaPlaylist.Random)

    def add_left_widgets(self):
        '''
        添加左部控件
        :return:
        '''
        self.left_close = QtWidgets.QPushButton()   # 关闭按钮
        self.left_visit = QtWidgets.QPushButton()   # 空白按钮
        self.left_mini = QtWidgets.QPushButton()    # 最小化按钮

        self.left_label_1 = QtWidgets.QPushButton("每日推荐")
        self.left_label_1.setObjectName('left_label')
        self.left_label_2 = QtWidgets.QPushButton("我的音乐")
        self.left_label_2.setObjectName('left_label')
        self.left_label_3 = QtWidgets.QPushButton("联系与帮助")
        self.left_label_3.setObjectName('left_label')

        # 在这里,我们使用qtawesome这个第三方库来实现按钮中的Font Awesome字体图标的显示
        self.left_button_1 = QtWidgets.QPushButton(qtawesome.icon('fa.music', color='white'), "华语流行")
        self.left_button_1.setObjectName('left_button')
        self.left_button_2 = QtWidgets.QPushButton(qtawesome.icon('fa.sellsy', color='white'), "在线FM")
        self.left_button_2.setObjectName('left_button')
        self.left_button_3 = QtWidgets.QPushButton(qtawesome.icon('fa.film', color='white'), "热门MV")
        self.left_button_3.setObjectName('left_button')
        self.left_button_4 = QtWidgets.QPushButton(qtawesome.icon('fa.home', color='white'), "本地音乐")
        self.left_button_4.setObjectName('left_button')
        self.left_button_5 = QtWidgets.QPushButton(qtawesome.icon('fa.download', color='white'), "下载管理")
        self.left_button_5.setObjectName('left_button')
        self.left_button_6 = QtWidgets.QPushButton(qtawesome.icon('fa.heart', color='white'), "我的收藏")
        self.left_button_6.setObjectName('left_button')
        self.left_button_7 = QtWidgets.QPushButton(qtawesome.icon('fa.comment', color='white'), "反馈建议")
        self.left_button_7.setObjectName('left_button')
        self.left_button_8 = QtWidgets.QPushButton(qtawesome.icon('fa.star', color='white'), "关注我们")
        self.left_button_8.setObjectName('left_button')
        self.left_button_9 = QtWidgets.QPushButton(qtawesome.icon('fa.question', color='white'), "遇到问题")
        self.left_button_9.setObjectName('left_button')
        self.left_xxx = QtWidgets.QPushButton(" ")

        # 将创建的按钮添加到左侧部件的网格布局层中
        self.left_layout.addWidget(self.left_mini, 0, 0, 1, 1)
        self.left_layout.addWidget(self.left_close, 0, 2, 1, 1)
        self.left_layout.addWidget(self.left_visit, 0, 1, 1, 1)
        self.left_layout.addWidget(self.left_label_1, 1, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_1, 2, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_2, 3, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_3, 4, 0, 1, 3)
        self.left_layout.addWidget(self.left_label_2, 5, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_4, 6, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_5, 7, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_6, 8, 0, 1, 3)
        self.left_layout.addWidget(self.left_label_3, 9, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_7, 10, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_8, 11, 0, 1, 3)
        self.left_layout.addWidget(self.left_button_9, 12, 0, 1, 3)


    def add_bottom_widgets(self):
        '''
        添加底部控件,
        :return:
        '''
        # 播放控制部件
        self.bottom_playconsole_widget = QtWidgets.QWidget()
        self.bottom_playconsole_widget.setObjectName('bottom_playconsole_widget')
        # self.bottom_playconsole_widget.setFixedSize(400, 120)
        self.bottom_playconsole_layout = QtWidgets.QGridLayout()
        self.bottom_playconsole_widget.setLayout(self.bottom_playconsole_layout)

        # 创建进度条
        self.bottom_process_bar = QtWidgets.QSlider(Qt.Horizontal)
        self.bottom_process_bar.setValue(49)
        # self.bottom_process_bar.setFixedHeight(5)  # 设置进度条高度
        self.bottom_process_bar.setObjectName('process_bar')
        # self.bottom_process_bar.setTextVisible(False)  # 不显示进度条文字

        # 创建显示播放剩余时间
        self.bottom_time_label = QtWidgets.QLabel()
        self.bottom_time_label.setText("<font color='#FFB6C1'>--/--</font>")
        # 创建按钮的布局
        self.bottom_console_layout = QHBoxLayout()

        self.bottom_console_button_1 = QtWidgets.QPushButton(qtawesome.icon('fa.backward', color='#FFB6C1'), '')
        self.bottom_console_button_2 = QtWidgets.QPushButton(qtawesome.icon('fa.forward', color='#FFB6C1'), '')
        # <i class="far fa-pause" />
        self.bottom_console_button_3 = QtWidgets.QPushButton(qtawesome.icon('fa.play', color='#FFB6C1', font=15), '')
        self.bottom_console_button_3.setIconSize(QtCore.QSize(25, 25))

        self.bottom_console_layout.addWidget(self.bottom_console_button_1)
        self.bottom_console_layout.addWidget(self.bottom_console_button_3)
        self.bottom_console_layout.addWidget(self.bottom_console_button_2)
        # 设置布局内的控件居中
        self.bottom_console_layout.setAlignment(QtCore.Qt.AlignCenter)

        self.bottom_playconsole_layout.addLayout(self.bottom_console_layout, 0, 2, 1, 3)
        # self.bottom_playconsole_layout.addLayout(self.bottom_process_layout, 1, 0, 1, 5)
        self.bottom_playconsole_layout.addWidget(self.bottom_process_bar, 1, 1, 1, 4)
        self.bottom_playconsole_layout.addWidget(self.bottom_time_label, 1, 5)


        # 播放封面控件
        self.bottom_music_widget = QWidget()
        self.bottom_music_widget.setFixedSize(250, 70)
        self.bottom_music_layout = QGridLayout()
        self.bottom_music_widget.setLayout(self.bottom_music_layout)
        # 音乐封面固定不变
        self.bottom_music = QtWidgets.QLabel()
        self.bottom_music.setFixedSize(120, 70)
        self.bottom_music.setObjectName('bottom_music')
        self.bottom_music.setScaledContents(True)
        # 歌曲名和歌手
        self.bottom_music_name = QLabel()
        self.bottom_music_singer = QLabel()
        # 添加控件
        self.bottom_music_layout.addWidget(self.bottom_music, 0, 0, 2, 2)
        self.bottom_music_layout.addWidget(self.bottom_music_name, 0, 2, 1, 1)
        self.bottom_music_layout.addWidget(self.bottom_music_singer, 1, 2, 1, 1)
        self.bottom_music_layout.setAlignment(Qt.AlignLeft)


        # 底部的右边自成一个widget
        self.bottom_right_widget = QtWidgets.QWidget()
        self.bottom_right_layout = QHBoxLayout()
        self.bottom_right_widget.setLayout(self.bottom_right_layout)
        # 音量滑条
        self.bottom_volume_slider = QSlider(Qt.Horizontal)
        self.bottom_volume_slider.setValue(80)
        self.bottom_volume_slider.setFixedSize(90, 10)
        # 音量按钮
        # 静音是fa.volume-mute
        self.bottom_sound_btn = QPushButton(qtawesome.icon('fa.volume-up',  color='#FFB6C1'), '')
        # 播放模式按钮
        self.bottom_mode_btn = QPushButton(qtawesome.icon('fa.random', color='#FFB6C1'), '')
        self.bottom_mode_btn.setToolTip('随机播放')
        """ fa.repeat  列表循环"""
        """ fa.repeat-1 单曲循环"""
        self.bottom_right_layout.addWidget(self.bottom_mode_btn)
        self.bottom_right_layout.addWidget(self.bottom_sound_btn)
        self.bottom_right_layout.addWidget(self.bottom_volume_slider)

        self.bottom_layout.addWidget(self.bottom_music_widget, 0, 0, 1, 2)
        # self.bottom_layout.addStretch(1)
        self.bottom_layout.addWidget(self.bottom_playconsole_widget, 0, 4, 1, 6)
        # self.bottom_layout.addStretch(0)
        self.bottom_layout.addWidget(self.bottom_right_widget, 0, 10, 1, 2)


    def signal_init(self):
        """添加按钮响应事件"""
        self.left_button_1.clicked.connect(lambda: self.right_widget.setCurrentIndex(0))
        self.left_button_2.clicked.connect(lambda: self.right_widget.setCurrentIndex(1))
        self.left_button_3.clicked.connect(lambda: self.right_widget.setCurrentIndex(2))
        self.left_button_4.clicked.connect(lambda: self.right_widget.setCurrentIndex(3))
        self.left_button_5.clicked.connect(lambda: self.right_widget.setCurrentIndex(2))
        self.left_button_6.clicked.connect(lambda: self.right_widget.setCurrentIndex(2))
        self.left_button_7.clicked.connect(lambda: self.right_widget.setCurrentIndex(6))
        self.left_button_8.clicked.connect(lambda: self.right_widget.setCurrentIndex(6))
        self.left_button_9.clicked.connect(lambda: self.right_widget.setCurrentIndex(6))


        # todo 添加底部按钮响应时间
        self.bottom_sound_btn.clicked.connect(lambda: self.btn_func(self.bottom_sound_btn))
        self.bottom_console_button_1.clicked.connect(lambda: self.btn_func(self.bottom_console_button_1))
        self.bottom_console_button_3.clicked.connect(lambda: self.btn_func(self.bottom_console_button_3))
        self.bottom_console_button_2.clicked.connect(lambda: self.btn_func(self.bottom_console_button_2))
        self.bottom_mode_btn.clicked.connect(lambda: self.btn_func(self.bottom_mode_btn))
        # self.list_btn.clicked.connect(lambda: self.btn_func(self.list_btn))
        #
        self.bottom_volume_slider.valueChanged.connect(self.volume_slider_func)
        self.local_songs_widget.doubleClicked.connect(self.table_play_func)
        # 分别利用durationChanged来监听获取时长,positionChanged信号会在当前播放时长(position)改变的时候发射
        self.player.durationChanged.connect(self.get_duration_func)
        self.player.positionChanged.connect(self.get_position_func)
        # todo 通过手动改变滑动条改变播放进度,而sliderMoved之歌信号只有在用户手动改变滑动条值的情况下才会发射
        self.bottom_process_bar.sliderMoved.connect(self.update_position_func)
        # 如果播放列表中的正在播放的歌曲播放完,然后改变,那对应的播放按钮应该改成pause的形状
        self.play_list.currentIndexChanged.connect(self.update_console_btn_func)

        # 打开文件格式(*.mp3)文件,添加到播放列表中
        self.local_add_song_btn.clicked.connect(self.add_song)
        # 选择文件夹并打开,然后添加文件夹下面的歌曲
        self.local_add_dic_btn.clicked.connect(self.add_dic)
        # 当播放列表中单元格被右键点击的时候,弹出上下文菜单用以删除歌曲
        self.local_songs_widget.customContextMenuRequested.connect(self.generateMenu)
        # 删除所有歌曲按钮点击事件
        self.local_del_songs_btn.clicked.connect(self.del_all_songs)


    def btn_func(self, btn):
        '''根据按钮不同,设置不同的响应事件'''
        if btn == self.bottom_sound_btn:
            if self.player.isMuted():
                self.player.setMuted(False)
                self.bottom_sound_btn.setIcon(qtawesome.icon('fa.volume-up',  color='#FFB6C1'))
            else:
                self.player.setMuted(True)
                self.bottom_sound_btn.setIcon(qtawesome.icon('fa.volume-off',  color='#FFB6C1'))


        elif btn == self.bottom_console_button_1:
            if self.play_list.currentIndex() == 0:
                # 如果当前这首歌为0,那上一首就是最后一首歌
                self.play_list.setCurrentIndex(self.play_list.mediaCount() - 1)
            else:
                # 直接调用方法,找到上一首
                self.play_list.previous()
            self.player.play()
            self.bottom_console_button_3.setIcon(qtawesome.icon('fa.pause',  color='#FFB6C1'))

        elif btn == self.bottom_console_button_3:
            # 如果播放列表为空,那随意,点不动
            if self.play_list.isEmpty() == True:
                pass
            else:
                if self.player.state() == 1:
                    # 如果正在播放,那就暂停
                    self.player.pause()
                    self.bottom_console_button_3.setIcon(qtawesome.icon('fa.play',  color='#FFB6C1'))
                else:
                    self.player.play()
                    self.bottom_console_button_3.setIcon(qtawesome.icon('fa.pause',  color='#FFB6C1'))

        elif btn == self.bottom_console_button_2:
            if self.play_list.currentIndex() == self.play_list.mediaCount() - 1:
                self.play_list.setCurrentIndex(0)
            else:
                self.play_list.next()
            self.player.play()
            self.bottom_console_button_3.setIcon(qtawesome.icon('fa.pause',  color='#FFB6C1'))

        elif btn == self.bottom_mode_btn:  # 5
            if self.play_list.playbackMode() == 2:
                self.play_list.setPlaybackMode(QMediaPlaylist.Loop)

                self.bottom_mode_btn.setIcon(QIcon('./images/repeat-once.png'))
                self.bottom_mode_btn.setToolTip('单曲循环')

            elif self.play_list.playbackMode() == 3:
                self.play_list.setPlaybackMode(QMediaPlaylist.Random)
                self.bottom_mode_btn.setIcon(qtawesome.icon('fa.random', color='#FFB6C1'))
                self.bottom_mode_btn.setToolTip('随机播放')

            elif self.play_list.playbackMode() == 4:
                self.play_list.setPlaybackMode(QMediaPlaylist.Sequential)
                self.bottom_mode_btn.setIcon(qtawesome.icon('fa.repeat', color='#FFB6C1'))
                self.bottom_mode_btn.setToolTip('列表循环')
            # print(self.play_list.playbackMode())


    def volume_slider_func(self, value):
        '''音量滑块滑动事件'''
        self.player.setVolume(value)
        if value == 0:
            self.bottom_sound_btn.setIcon(qtawesome.icon('fa.volume-off',  color='#FFB6C1'))
        else:
            if self.player.isMuted():
                self.player.setMuted(False)
            self.bottom_sound_btn.setIcon(qtawesome.icon('fa.volume-up',  color='#FFB6C1'))

    def table_play_func(self, index):
        self.play_list.setCurrentIndex(index.row())
        self.player.play()
        self.bottom_console_button_3.setIcon(qtawesome.icon('fa.pause',  color='#FFB6C1'))

    def get_duration_func(self, d):
        """d是文件时长,单位是毫秒"""
        self.bottom_process_bar.setRange(0, d)
        self.bottom_process_bar.setEnabled(True)
        # 在get_time_func中更新时间
        self.get_time_func(d)

    def get_time_func(self, d):
        '''首先获取分钟数和秒数,然后判断是否已经播放完毕(即分秒都为0)。
        如果播放结束的话,则将时间文本设为--/--,
        而且还要将播放按钮的图标设为暂停;否则就设置文本设为剩余时间。'''
        seconds = int(d/1000)
        minutes = int(seconds/60)
        seconds -= minutes*60
        if minutes == 0 and seconds == 0:
            # 如果直接手动改变滑条,直接滑到底了,那就直接暂停了
            self.bottom_time_label.setText("<font color='#FFB6C1'>--/--</font>")
            # self.bottom_console_button_3.setIcon(qtawesome.icon('fa.play',  color='#FFB6C1'))
        else:
            self.bottom_time_label.setText("<font color='#FFB6C1'>{}:{}</font>".format(minutes, seconds))

    def get_position_func(self, p):
        self.bottom_process_bar.setValue(p)
        d = self.bottom_process_bar.maximum() - p
        self.get_time_func(d)

    def update_position_func(self, value):
        '''调用QMediaPlayer的setPosition()方法并传入progress_slider的值来设置当前播放进度,
        那剩余时间就是进度条最大值减去当前值,接着我们将剩余时间d传入get_time_func来更新即可。'''
        self.player.setPosition(value)
        d = self.bottom_process_bar.maximum() - value
        self.get_time_func(d)

    def update_console_btn_func(self, index):
        self.bottom_music_name.setText("<font color='#FFB6C1'>{}</font>".format(self.local_songs_model.index(index, 0).data()))
        self.bottom_music_singer.setText(
            "<font color='#FFB6C1'>{}</font>".format(self.local_songs_model.index(index, 1).data()))
        self.bottom_console_button_3.setIcon(qtawesome.icon('fa.pause', color='#FFB6C1'))

    def add_song(self):
        """从文件夹中添加MP3文件,然后添加到播放列表中"""
        # fname 是绝对路径
        fname, _ = QFileDialog.getOpenFileName(self, 'Open file', '', 'MP3 files (*.mp3)')
        if fname == '':
            pass
        else:
            self.add_song_from_path(fname)


    def add_song_from_path(self, path):
        '''根据路径添加歌曲'''
        if path not in self.media_list:
            # 如果该路径本来不存在在media_list中,那么在media_list中添加,然后再添加到存取歌曲路径的文件里面,从而可以在下次打开后,仍保存着这次添加的歌曲
            self.media_list.append(path)
            duration = MP3(path).info.length
            minutes = int(duration / 60)
            seconds = int(duration - minutes * 60)
            # 如果只是添加单首歌曲,那就采用追加写的方式
            # 同时加一个换行符,以便于读取
            with open('songs.txt', 'a', encoding='utf-8') as f:
                # 如果文件中没有歌曲,也就是self.media_list长度为1,那从第一行写,不需要加换行符
                if len(self.media_list) == 1:
                    f.write(path)
                else:
                    f.write('\n' + path)
            self.media_duration.append('{}:{}'.format(minutes, seconds))
            # 在播放列表中添加
            self.play_list.addMedia(QMediaContent(QUrl.fromLocalFile(path)))
            # 在表单中添加
            index = len(self.media_list) - 1
            m = self.media_list[-1]
            song = m.split('/')[-1]  # song获取到 歌曲名.mp3
            l = song.split('.')
            # 获取歌曲名字
            self.local_songs_model.setItem(index, 0, QStandardItem(l[0].split('_')[0]))
            # 获取歌手名字
            try:
                self.local_songs_model.setItem(index, 1, QStandardItem(l[0].split('_')[1]))
            except:
                self.local_songs_model.setItem(index, 1, QStandardItem('未知歌手'))
            # 填充歌曲长度
            self.local_songs_model.setItem(index, 2, QStandardItem(self.media_duration[index]))
        else:
            song_name = path.split('/')[-1]
            QMessageBox.information(self, '提醒', '歌曲 {} 已经存在于歌单中,请勿重复添加!'.format(song_name), QMessageBox.Yes)


    def add_dic(self):
        """"""
        self.dir_path = QFileDialog.getExistingDirectory(None, '选择路径', os.getcwd())
        if self.dir_path == '':
            pass
        # self.lineEidt.setText(self.dir_path)
        else:
            self.getFiles(self.dir_path)
        # except Exception as e:
        #     QMessageBox.warning(self, '警告', e, QMessageBox.Yes)
            # print(e)

    def getFiles(self, path):
        """将文件夹下的.mp3文件写到文件里面,并添加到播放列表里面"""
        self.file_list = os.listdir(path)
        # print(self.list)
        del_files = []
        for m in self.file_list:
            if m.find('.mp3') == -1:
                del_files.append(m)
        for file in del_files:
            self.file_list.remove(file)
        for file in self.file_list:
            p = path + '/' +file
            self.add_song_from_path(p)

    def generateMenu(self, pos):
        """pos是点击的位置相对于控件的坐标"""
        for i in self.local_songs_widget.selectionModel().selection().indexes():
            row = i.row()   # 获取当前点击的位置所处的行数
        self.local_menu = QMenu()  # 创建上下文菜单实例
        item1 = self.local_menu.addAction('删除当前选中的歌曲')
        # 将pos坐标位置转变为相对于屏幕的坐标
        screenPos = self.local_songs_widget.mapToGlobal(pos)
        # 返回值action是菜单出现后,鼠标点击的动作,参数screenPos是菜单出现的位置
        action = self.local_menu.exec_(screenPos)
        if action == item1:
            self.media_list.pop(row)
            self.media_duration.pop(row)
            # 将列表重新写入文件中,从而实现永久删除
            with open('songs.txt', 'w', encoding='utf-8') as f:
                string = '\n'.join(self.media_list)
                f.write(string)
            # 将该歌曲移除播放列表和表单中
            if self.play_list.currentIndex() == row:
                # 如果当前歌曲在播放
                self.play_list.removeMedia(row)
                # 那么就获取下一首歌的index
                index = self.play_list.currentIndex()
                # index+1是因为删除了一首歌之后,歌曲的index相较于原来会-1
                song_name = self.local_songs_model.index(index+1, 0).data()
                singer_name = self.local_songs_model.index(index+1, 1).data()
                # 将歌曲label信息更换
                self.bottom_music_name.setText(
                    "<font color='#FFB6C1'>{}</font>".format(song_name))
                self.bottom_music_singer.setText(
                    "<font color='#FFB6C1'>{}</font>".format(singer_name))
            else:
                self.play_list.removeMedia(row)
            self.local_songs_model.removeRow(row)
        else:
            pass

    def del_all_songs(self):
        """删除所有歌曲"""
        # 首先弹出对话框
        reply = QMessageBox.information(self, "提示", "真的要删除所有歌曲吗??", QMessageBox.Yes | QMessageBox.No)
        if reply == QMessageBox.Yes:
            # 清空播放列表
            self.play_list.clear()
            self.bottom_console_button_3.setIcon(qtawesome.icon('fa.play', color='#FFB6C1'))
            # 清空表单中的所有行
            self.local_songs_model.removeRows(0, self.local_songs_model.rowCount())
            # print(len(self.media_list))
            for i in range(len(self.media_list)):
                self.media_list.pop(0)
                self.media_duration.pop(0)
            # 将文件中的信息清空
            with open('songs.txt', 'w', encoding='utf-8') as f:
                f.write('')
            # 将歌曲信息的label设为空
            self.bottom_music_name.setText('')
            self.bottom_music_singer.setText('')
        else:
            pass

    def UI_hua(self):
        '''
        设置 华语流行 对应的界面

        :return:
        '''
        self.popular_layout = QtWidgets.QVBoxLayout()
        self.right_widget_popular.setLayout(self.popular_layout)
        self.hua_layout = QtWidgets.QGridLayout()
        # 设置 华语流行 界面的布局
        self.rigth_widget_hua.setLayout(self.hua_layout)

        # 推荐模块
        # 标题
        self.hua_recommend_label = QtWidgets.QLabel('今日推荐')
        self.hua_recommend_label.setObjectName('hua_label')
        # 创建推荐的移动窗口实例
        self.hua_recommend_widget = move_window()
        self.hua_recommend_widget.setFixedSize(self.hua_recommend_widget_width, self.hua_recommend_widget_height)
        # print("width: ", self.width())
        # print("height: ", self.height())

        self.hua_layout.addWidget(self.hua_recommend_label, 0, 0, 1, 9)
        self.hua_layout.addWidget(self.hua_recommend_widget, 2, 1, 7, 9)


        # 音乐歌单模块代码如下
        # 标题
        self.hua_palylist_lable = QtWidgets.QLabel("推荐歌单")
        self.hua_palylist_lable.setObjectName('rigth_lable')
        # 主部件和布局
        self.hua_palylist_widget = QtWidgets.QWidget()
        self.hua_palylist_layout = QtWidgets.QGridLayout()
        self.hua_palylist_widget.setLayout(self.hua_palylist_layout)

        # 歌单控件
        """
        每日推荐、心碎:你短暂停留,我倾尽所有
        甜妹当然也要有甜甜的歌单呀
        甜甜恋曲:我爱你在地球上也不是什么大秘密
        诗与民谣|生活变成了歌,奏响心底的荒芜
        旅行丨曾梦想仗剑走天涯,看一看世界的繁华
        夏日入侵企画/棱镜/告五人/落日飞车/橘子海
        治愈华语|热闹之外,拥有平静独处的能力
        只珍朝夕|在细水长流的日子里,只珍朝夕
        “喜欢不一定非要谈恋爱.”
        """
        self.hua_icon_size = QSize(150, 150)
        self.hua_palylist_btn_1 = QtWidgets.QToolButton()
        self.hua_palylist_label_1 = QtWidgets.QLabel()
        self.hua_palylist_label_1.setText("每日歌曲推荐")
        self.hua_palylist_btn_1.setIcon(QtGui.QIcon('./images/歌单0.png'))
        self.hua_palylist_btn_1.setIconSize(self.hua_icon_size)
        # 设置文字在图标下方
        # self.hua_palylist_btn_1.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_2 = QtWidgets.QToolButton()
        self.hua_palylist_label_2 = QtWidgets.QLabel()
        self.hua_palylist_label_2.setText("心碎:你短暂停留,\n我倾尽所有")
        self.hua_palylist_btn_2.setIcon(QtGui.QIcon('./images/歌单1.jpg'))
        self.hua_palylist_btn_2.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_2.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_3 = QtWidgets.QToolButton()
        self.hua_palylist_label_3 = QtWidgets.QLabel()
        self.hua_palylist_label_3.setText("甜妹当然也要有甜甜\n的歌单呀")
        self.hua_palylist_btn_3.setIcon(QtGui.QIcon('./images/歌单2.jpg'))
        self.hua_palylist_btn_3.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_3.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_4 = QtWidgets.QToolButton()
        self.hua_palylist_label_4 = QtWidgets.QLabel()
        self.hua_palylist_label_4.setText("甜甜恋曲:我爱你在\n地球上也不是什么大秘密")
        self.hua_palylist_btn_4.setIcon(QtGui.QIcon('./images/歌单3.jpg'))
        self.hua_palylist_btn_4.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_4.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_5 = QtWidgets.QToolButton()
        self.hua_palylist_label_5 = QtWidgets.QLabel()
        self.hua_palylist_label_5.setText("诗与民谣|生活变成\n了歌,奏响心底的荒芜")
        self.hua_palylist_btn_5.setIcon(QtGui.QIcon('./images/歌单4.jpg'))
        self.hua_palylist_btn_5.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_5.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_6 = QtWidgets.QToolButton()
        self.hua_palylist_label_6 = QtWidgets.QLabel()
        self.hua_palylist_label_6.setText("旅行丨曾梦想仗剑走\n天涯,看一看世界的繁华")
        self.hua_palylist_btn_6.setIcon(QtGui.QIcon('./images/歌单5.jpg'))
        self.hua_palylist_btn_6.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_6.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_7 = QtWidgets.QToolButton()
        self.hua_palylist_label_7 = QtWidgets.QLabel()
        self.hua_palylist_label_7.setText("夏日入侵企画/棱镜/\n告五人/落日飞车/橘子海")
        self.hua_palylist_btn_7.setIcon(QtGui.QIcon('./images/歌单6.jpg'))
        self.hua_palylist_btn_7.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_7.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_8 = QtWidgets.QToolButton()
        self.hua_palylist_label_8 = QtWidgets.QLabel()
        self.hua_palylist_label_8.setText("治愈华语|热闹之外\n,拥有平静独处的能力")
        self.hua_palylist_btn_8.setIcon(QtGui.QIcon('./images/歌单7.jpg'))
        self.hua_palylist_btn_8.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_8.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_9 = QtWidgets.QToolButton()
        self.hua_palylist_label_9 = QtWidgets.QLabel()
        self.hua_palylist_label_9.setText("只珍朝夕|在细水长\n流的日子里,只珍朝夕")
        self.hua_palylist_btn_9.setIcon(QtGui.QIcon('./images/歌单8.jpg'))
        self.hua_palylist_btn_9.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_9.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)

        self.hua_palylist_btn_10 = QtWidgets.QToolButton()
        self.hua_palylist_label_10 = QtWidgets.QLabel()
        self.hua_palylist_label_10.setText("“喜欢不一定非要谈恋\n爱.”")
        self.hua_palylist_btn_10.setIcon(QtGui.QIcon('./images/歌单9.jpg'))
        self.hua_palylist_btn_10.setIconSize(self.hua_icon_size)
        # self.hua_palylist_btn_10.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon)


        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_1, 0, 0, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_1, 1, 0, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_2, 0, 1, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_2, 1, 1, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_3, 0, 2, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_3, 1, 2, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_4, 0, 3, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_4, 1, 3, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_5, 0, 4, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_5, 1, 4, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_6, 2, 0, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_6, 3, 0, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_7, 2, 1, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_7, 3, 1, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_8, 2, 2, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_8, 3, 2, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_9, 2, 3, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_9, 3, 3, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_btn_10, 2, 4, Qt.AlignCenter)
        self.hua_palylist_layout.addWidget(self.hua_palylist_label_10, 3, 4, Qt.AlignCenter)

        # self.hua_layout.addWidget(self.hua_scrollbar, 0, 9, 12, 1)
        self.hua_layout.addWidget(self.hua_palylist_lable, 9, 0, 1, 9)
        self.hua_layout.addWidget(self.hua_palylist_widget, 10, 0, 2, 9)

        # 滚动条控件
        self.hua_scrollbar = QScrollArea()
        self.hua_scrollbar.setWidget(self.rigth_widget_hua)
        # 将滚动区域自带的横向滚动条隐藏掉
        self.hua_scrollbar.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        self.popular_layout.addWidget(self.hua_scrollbar)


    def UI_local(self):
        '''
        设置本地音乐界面
        n:列表中歌曲数量
        :return:
        '''
        # 设置总布局
        self.local_layout = QtWidgets.QGridLayout()
        # 获取歌曲总数
        number = len(self.media_duration)
        # 设置存放歌曲信息的控件
        self.local_songs_widget = QtWidgets.QTableView()
        # 建立歌曲数据源
        self.local_songs_model = QStandardItemModel(number, 3)
        self.local_songs_model.setHorizontalHeaderLabels(['标题', '歌手', '时长'])
        if number != 0:
            for index, m in enumerate(self.media_list):
                song = m.split('/')[-1] # song获取到 歌曲名.mp3
                l = song.split('.')
                # 获取歌曲名字
                self.local_songs_model.setItem(index, 0, QStandardItem(l[0].split('_')[0]))
                # 获取歌手名字
                try:
                    self.local_songs_model.setItem(index, 1, QStandardItem(l[0].split('_')[1]))
                except:
                    self.local_songs_model.setItem(index, 1, QStandardItem('未知歌手'))
                # 填充歌曲长度
                self.local_songs_model.setItem(index, 2, QStandardItem(self.media_duration[index]))
        else:
            pass
        # 设置数据源model
        self.local_songs_widget.setModel(self.local_songs_model)
        # 水平方向标签拓展剩下的窗口部分,填满表格
        self.local_songs_widget.horizontalHeader().setStretchLastSection(True)
        # 水平方向,表格大小拓展到适当的尺寸
        self.local_songs_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        # 对第0列单独设置固定宽度
        self.local_songs_widget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)
        # 设置水平标签左对齐
        self.local_songs_widget.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        # 设置第0列的宽度为200
        self.local_songs_widget.setColumnWidth(0, 400)
        # 设置单元格内容为不可改
        self.local_songs_widget.setEditTriggers(QTableView.NoEditTriggers)
        # 允许上下文菜单
        self.local_songs_widget.setContextMenuPolicy(Qt.CustomContextMenu)
        # self.local_songs_widget.customContextMenuRequested.connect(self.generateMenu)   # 当单元格菜单被触发

        # local中添加歌曲控件
        self.local_add_songs_widget = QWidget()
        self.local_add_songs_layout = QHBoxLayout()
        self.local_add_songs_widget.setLayout(self.local_add_songs_layout)

        # 从文件中增加单首MP3歌曲
        self.local_add_song_btn = QPushButton(qtawesome.icon('fa.plus',  color='#FFB6C1'), '添加歌曲')
        # 选择文件夹并打开,然后在播放列表中添加文件夹下面的.mp3文件
        self.local_add_dic_btn = QPushButton(qtawesome.icon('fa.folder-open',  color='#FFB6C1'), '添加文件夹')
        # 删除播放列表中的所有歌曲
        self.local_del_songs_btn = QPushButton(qtawesome.icon('fa.rocket', color='#FFB6C1'), '删除所有歌曲')

        self.local_add_songs_layout.addWidget(self.local_add_song_btn)
        self.local_add_songs_layout.addWidget(self.local_add_dic_btn)
        self.local_add_songs_layout.addWidget(self.local_del_songs_btn)

        self.local_layout.addWidget(self.local_add_songs_widget, 0, 0, 1, 12)
        self.local_layout.addWidget(self.local_songs_widget, 1, 0, 10, 12)

        self.right_widget_local.setLayout(self.local_layout)


    def UI_FM(self):
        """设置在线FM的布局"""
        self.FM_layout = QGridLayout()

        self.FM_label_1 = QLabel()
        self.FM_label_1.setText("<font color=red, size='8'>什么?你还不知道这个网站,点击下方链接获得同款喔!</font>")  # 设置文本内容的时候可以使用html语言
        self.FM_label_1.setAutoFillBackground(True)      # true为显示背景填充色
        palette = QPalette()
        palette.setColor(QPalette.Window, Qt.gray)  # 设置背景填充色为 Qt中的蓝色,QPalette.window指窗口部件的背景色
        self.FM_label_1.setPalette(palette)
        # self.FM_label_1.setAlignment(Qt.AlignCenter)     # 设置文本对齐方式为中心对齐

        self.FM_label_2 = QLabel()
        movie = QMovie('./images/向日葵.gif')
        self.FM_label_2.setMovie(movie)
        movie.start()
        self.FM_label_2.setFixedSize(300, 300)
        self.FM_label_2.setScaledContents(True)


        self.FM_label_3 = QLabel()
        self.FM_label_3.setAlignment(Qt.AlignRight)
        self.FM_label_3.setToolTip('这都不点进去看看??')
        self.FM_label_3.setOpenExternalLinks(True)       # ture表示点击该label则打开网页
        self.FM_label_3.setText("<a href='https://tonzhon.com/'><font color='#FFB6C1',size='8'>一个音乐网站</font></a>")

        self.FM_layout.addWidget(self.FM_label_1, 0, 0, 1, 4)
        self.FM_layout.addWidget(self.FM_label_2, 1, 0, 1, 4)
        self.FM_layout.addWidget(self.FM_label_3, 2, 3, 1, 1)
        self.FM_layout.setAlignment(Qt.AlignCenter)

        self.right_widget_FM.setLayout(self.FM_layout)

    def UI_MV(self):
        """功能未实现页面"""
        self.MV_layout = QGridLayout()

        self.MV_label1 = QLabel()
        movie_1 = QMovie("./images/猫爪.gif")
        self.MV_label1.setMovie(movie_1)
        movie_1.start()
        self.MV_label1.setFixedSize(60, 40)
        self.MV_label1.setScaledContents(True)

        self.MV_label2 = QLabel()
        self.MV_label2.setText("<font color='#FFB6C1', size='8'>该页面功能正在骑马来的路上!!!</font>")

        self.MV_label3 = QLabel()
        movie_2 = QMovie("./images/加载.gif")
        self.MV_label3.setMovie(movie_2)
        movie_2.start()
        self.MV_label3.setFixedSize(400, 400)
        self.MV_label3.setScaledContents(True)

        self.MV_layout.addWidget(self.MV_label1, 0, 0, 1, 1)
        self.MV_layout.addWidget(self.MV_label2, 0, 1, 1, 4)
        self.MV_layout.addWidget(self.MV_label3, 1, 0, 3, 4)
        self.MV_layout.setAlignment(Qt.AlignCenter)

        self.right_widget_MV.setLayout(self.MV_layout)

    def UI_suggest(self):
        """设置V我50界面"""
        self.suggest_layout = QGridLayout()
        self.right_widget_suggest.setLayout(self.suggest_layout)

        # 设置label
        self.suggest_label1 = QLabel()
        self.suggest_label1.setText("<font color=red, size='8'>什么?你想支持作者?太感动辣!!!</font>")  # 设置文本内容的时候可以使用html语言
        self.suggest_label1.setAlignment(Qt.AlignCenter)  # 设置文本对齐方式为中心对齐

        self.suggest_label2 = QLabel()
        movie_1 = QMovie("./images/委屈.gif")
        self.suggest_label2.setMovie(movie_1)
        movie_1.start()
        self.suggest_label2.setFixedSize(60, 40)
        self.suggest_label2.setScaledContents(True)

        self.suggest_label3 = QLabel()
        self.suggest_label3.setAlignment(Qt.AlignCenter)  # 中心对齐
        self.suggest_label3.setToolTip('快V我50')  # 设置控件提示信息
        self.suggest_label3.setFixedSize(400, 400)
        self.suggest_label3.setPixmap(QPixmap("./images/v50.png"))  # 显示图片

        self.suggest_label4 = QLabel()
        self.suggest_label4.setAlignment(Qt.AlignRight)
        self.suggest_label4.setToolTip('速速点击!!!')
        self.suggest_label4.setOpenExternalLinks(True)  # ture表示点击该label则打开网页
        self.suggest_label4.setText("<a href='https://nuggetspin.mov/'><font color='#FFC0CB', size='8'>点击进入转账页面!</font></a>")

        self.suggest_layout.addWidget(self.suggest_label1, 0, 0, 1, 3)
        self.suggest_layout.addWidget(self.suggest_label2, 0, 3, 1, 1)
        self.suggest_layout.addWidget(self.suggest_label3, 1, 0, 3, 4)
        self.suggest_layout.addWidget(self.suggest_label4, 4, 0, 1, 4)
        self.suggest_layout.setAlignment(Qt.AlignCenter)



    def pretty_UI(self):
        '''
        美化窗口部件
        :return:
        '''
        # 设置左边部件的三个按钮
        self.left_close.setFixedSize(15, 15)
        self.left_visit.setFixedSize(15, 15)
        self.left_mini.setFixedSize(15, 15)
        self.left_close.setStyleSheet("""QPushButton{backfround:#F76677;border-radius:5px}QPushButton:hover{background:red;}""")
        self.left_visit.setStyleSheet("""QPushButton{backfround:#F7D674;border-radius:5px}QPushButton:hover{background:yellow;}""")
        self.left_mini.setStyleSheet("""QPushButton{backfround:#F6DDF6D;border-radius:5px}QPushButton:hover{background:green;}""")
        # 设置左侧菜单中的按钮和文字
        # 颜色设置为白色,并将按钮的边框去掉
        self.left_widget.setStyleSheet("""
        QPushButton{border:none;color:white;}
        QPushButton#left_label{
            border:none;
            border-bottom:1px solid white;
            font-size:18px;
            font-weight:700;
            font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
        }
        QPushButton#left_button:hover{border-left:4px solid red; font-weight:700;}
        """)

        # 设置top_widget上的搜索框和文字

        self.top_widget.setStyleSheet("""
            QLineEdit{
                border:0px;    
                margin:10px;
                margin-left:30px; 
                margin-right:30px;
                border-bottom: 2px solid #B3B3B3;
                font-family:'Microsoft YaHei';
                font-size:18px;
                font-weight:bold;
                }       
            QLineEdit:hover{
                border-bottom: 3px solid #66A3FF;
                }
            QLineEdit:focus{
                border-bottom: 3px solid #E680BD;
                }
            QPushButton{border:none;color:white;margin-right:5px;}
                QLabel{
                font-size:18px;
    }
        """)
        # 设置推荐模块的标题
        self.hua_recommend_label.setStyleSheet("""
            QLabel{
            border:none;
            font-size:16px;
            font-weight:700;
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
        """)
        # 设置歌单模块的标题以及歌单
        self.hua_palylist_lable.setStyleSheet("""
            QLabel{
            border:none;
            font-size:16px;
            font-weight:700;
            font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
            }
        """)
        self.hua_palylist_widget.setStyleSheet("""
            QLabel{border:none;font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;}
            QToolButton{border-radius:20px;}
            QToolButton:hover{border-bottom:2px solid #F&6677;}
        """)
        # 设置底部进度条和按钮
        self.bottom_widget.setStyleSheet("""
            QLabel#bottom_music{border-radius:10px;border-image:url(./images/你的名字.jpg)}
            QPushButton{border:none;color:#FFB6C1;}
            QSlider::sub-page:horizontal{
                background:#FFB6C1;
                border-radius:2px;
                margin-top:8px;
                margin-bottom:8px;
            }
            QSlider::add-page:horizontal{
                background:gray;
                border-radius:2px;
                margin-top:9px;
                margin-bottom:9px;
            }
            QSlider::handle:horizontal{
                background:#FFB6C1;
                width:5px;
                border:1px solid #FFB6C1;
                border-radius:2px;
                margin-top:6px;
                margin-bottom:6px;
            }
            QSlider::handle:horizontal:hover{
                background:#FFB6C1;
                width:10px;
                border:1px solid #FFB6C1;
                border-radius:5px;
                margin-top:4px;
                margin-bottom:4px;
            }
            QSlider#process_bar::handle:horizontal{
                background:#87CEFA;
                width:5px;
                border:2px solid #FFB6C1;
                border-radius:2px;
                margin-top:10px;
                margin-bottom:10px;
            }
            QSlider#process_bar::handle:horizontal:hover{
                background:#87CEFA;
                width:8px;
                border:2px solid #FFB6C1;
                border-radius:5px;
                margin-top:7px;
                margin-bottom:7px;
            }
            QWidget#bottom_playconsole_widget{
                margin-left:30px; 
                margin-right:30px;
            }
        """)
        # 设置窗口透明度
        self.setWindowOpacity(0.9)
        # 设置窗口背景透明
        self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
        # 防止窗口背景设置为透明后,部件不容易显示,将其背景颜色变为灰色
        self.setStyleSheet("""
        QWidget{
            background:gray;
            border-top-left-radius:10px;
            border-bottom-left-radius:10px;
        }
        """)

        self.right_widget_popular.setStyleSheet("""
        QScrollArea{
            border: 0px solid;
            border-right-width:0px;
            border-right-color:#dcdbdc;
            }
            QScrollBar:vertical {
            border:none;
            background:#f5f5f7;
            width:10px;
            margin: 0px 0 0px 0;
            }
            QScrollBar::handle:vertical {
            background:Gainsboro;
            min-height:20px;
            border-radius:5px;
            border:none;
            }
            QScrollBar::add-line:vertical {
            border: 0px solid grey;
            background:#32CC99;
            height:0px;
            subcontrol-position:bottom;
            subcontrol-origin:margin;
            }
            QScrollBar::sub-line:vertical {
            border: 0px solid grey;
            background:#32CC99;
            height:0px;
            subcontrol-position:top;
            subcontrol-origin:margin;
            }
            QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical {
            background:none;
            width:0px;
            height:0px;
            }
        """)
        # 设置歌曲播放页面的样式
        self.right_widget_local.setStyleSheet('''
            QHeaderView::section{
                background-color:gray;
                color:rgb(200,200,200);
                border:1px solid rgb(60,60,60);
                border-bottom:1px  #696969;
                height:27px;
            }
            QHeaderView::section:hover
            {
                background-color:rgb(80,80,80);
            }
            /*QTableView 左上角样式*/
            QTableView QTableCornerButton::section {
                background-color:gray;/*背景色*/
                border:1px solid rgb(60,60,60);/*边框*/
                border-radius:0px;/*边框圆角*/
             }

            QTableView{
                color:#7FFFD4;
                border: none;          /*边框颜色*/
                gridline-color:	#696969;             /*grid线颜色*/
        
                alternate-background-color: rgb(200, 200, 200); /*行交替颜色*/
                selection-background-color: rgb(255,182,193); /*选中行背景颜色*/
            }
            QPushButton{border:none;color:white;}
            QPushButton{
                border:none;
                border-bottom:1px solid #FFC0CB;
                font-size:18px;
                font-weight:700;
                font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;
            }
            QPushButton:hover{border-bottom:4px solid #48D1CC; font-weight:700;}
    ''')
        # 设置本地歌曲播放界面的滚动条
        self.local_songs_widget.verticalScrollBar().setStyleSheet("""
            QScrollBar{
            border:none;
            background:#f5f5f7;
            width:10px;
            margin: 0px 0 0px 0;
            }
            QScrollBar::handle{
            background:Gainsboro;
            min-height:20px;
            border-radius:5px;
            border:none;
            }
            QScrollBar::add-line{
            border: 0px solid grey;
            background:#32CC99;
            height:0px;
            subcontrol-position:bottom;
            subcontrol-origin:margin;
            }
            QScrollBar::sub-line{
            border: 0px solid grey;
            background:#32CC99;
            height:0px;
            subcontrol-position:top;
            subcontrol-origin:margin;
            }
            QScrollBar::add-page, QScrollBar::sub-page{
            background:none;
            width:0px;
            height:0px;
            }
        """)




    # 鼠标移动事件
    def mouseMoveEvent(self, a0: QtGui.QMouseEvent):
        if self._startPos:
            self._endPos = a0.pos() - self._startPos
            # 移动窗口
            self.move(self.pos() + self._endPos)

    # 鼠标按下事件
    def mousePressEvent(self, a0: QtGui.QMouseEvent):
        # 根据鼠标按下时的位置判断是否在QFrame范围内
        if self.childAt(a0.pos().x(), a0.pos().y()).objectName() == "top_widget":
            # 判断鼠标按下的是左键
            if a0.button() == QtCore.Qt.LeftButton:
                self._isTracking = True
                # 记录初始位置
                self._startPos = QtCore.QPoint(a0.x(), a0.y())

    # 鼠标松开事件
    def mouseReleaseEvent(self, a0: QtGui.QMouseEvent):
        if a0.button() == QtCore.Qt.LeftButton:
            self._isTracking = False
            self._startPos = None
            self._endPos = None

    # 鼠标双击事件
    def mouseDoubleClickEvent(self, a0: QtGui.QMouseEvent):
        if self.childAt(a0.pos().x(), a0.pos().y()).objectName() == "top_widget":
            if a0.button() == QtCore.Qt.LeftButton:
                self.maxOrNormal()

def main():
    app = QtWidgets.QApplication(sys.argv)
    gui = MainUi()
    gui.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

下面是滑动窗口的代码:

from PyQt5 import QtCore
from PyQt5.QtCore import Qt, QRect, QPropertyAnimation, QUrl, QSize
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QGridLayout, QSlider, QVBoxLayout, QHBoxLayout, QPushButton, QGraphicsOpacityEffect, QMenu, QScrollArea, QHeaderView, QTableView
from PyQt5.QtGui import QMovie, QIcon, QStandardItem, QStandardItemModel, QPalette, QPixmap

import sys
import qtawesome

Q = QApplication(sys.argv)


class mylabel(QLabel):
    cur_left_Index = 0
    cur_right_Index = 0


class move_window(QWidget):
    def __init__(self):
        super(move_window, self).__init__()
        self.resize(800, 300)
        self.setWindowFlag(QtCore.Qt.FramelessWindowHint)
        self.label_height = self.height()
        self.l_width = self.width()
        self.init_swiper()
        self.loop_init_label()


    def init_swiper(self):
        self.layout = QHBoxLayout()
        # 设置按钮图标及其颜色
        self.left_btn = QPushButton(qtawesome.icon('fa.arrow-left', color='red'), '')
        self.left_btn.setWindowOpacity(0)
        # self.left_btn.resize(self.label_width//10, self.label_height//5)
        self.left_btn.clicked.connect(self.init_to_left_animation)
        self.right_btn = QPushButton(qtawesome.icon('fa.arrow-right', color='red'), '')
        # self.right_btn.resize(self.label_width//10, self.label_height//5)
        self.right_btn.clicked.connect(self.init_to_right_animation)
        # 统一设置按钮背景为透明
        self.setStyleSheet("""
        QPushButton{border:none;background:transparent;}
        """)
        # 设置按钮背景透明,同时按下后箭头外围多出一个绿色箭头
        self.left_btn.setStyleSheet("""
            QPushButton:pressed {
                border-image:url(./images/左箭头.png);
            }
        """)

        self.right_btn.setStyleSheet("""
                QPushButton:pressed {
                    border-image:url(./images/右箭头.png);
                }
            """)
        self.layout.addWidget(self.left_btn)
        self.layout.addStretch(0)
        self.layout.addWidget(self.right_btn)
        self.setLayout(self.layout)


    def loop_init_label(self):
        """对每个Qlabel装载gif图片,同时初始化设置他们的cur_left_Index、cur_right_Index以及位置"""
        name = []
        # 设置尺寸
        self.center_width = int(self.l_width*0.6)
        self.center_height = self.label_height
        self.center_x = self.l_width//5
        self.left_x = int(self.center_x*2)
        self.right_x = int(self.center_x*0.6)
        self.side_y = self.label_height//8
        self.side_width = int(self.center_width*0.8)
        self.side_hight = int(self.center_height*0.67)

        for i in range(0, 4):
            label = 'label' + str(i)
            name.append(label)
        for i in range(0, len(name)):
            self.name = name
            self.name[i] = mylabel(self)
            self.name[i].cur_left_Index = i
            self.name[i].cur_right_Index = i

            if i == 0:
                m1 =QMovie('./images/皮卡丘.gif')
                self.name[i].setMovie(m1)
                m1.start()
                self.name[i].setGeometry(self.center_x, 0, self.center_width, self.center_height)
                self.name[i].setScaledContents(True)
                continue
            if i == 1:
                m2 = QMovie('./images/摇头 .gif')
                self.name[i].setMovie(m2)
                m2.start()
                self.name[i].setGeometry(self.right_x, self.side_y, self.side_width, self.side_hight)
                self.name[i].setScaledContents(True)


                continue
            if i == 2:
                m3 = QMovie('./images/跳舞.gif')
                self.name[i].setMovie(m3)
                m3.start()
                self.name[i].setGeometry(self.center_x, 0, self.side_width, self.side_hight)
                self.name[i].setScaledContents(True)
                continue

            if i == 3:
                m4 = QMovie('./images/欺骗.gif')
                self.name[i].setMovie(m4)
                m4.start()
                self.name[i].setGeometry(self.left_x, self.side_y, self.side_width, self.side_hight)
                self.name[i].setScaledContents(True)
                continue


        self.name_=name
        # 设置第0个label突出显示
        self.name_[0].raise_()

        # print('标签初始化完毕')

    def init_to_left_animation(self):
        """向左移动动画"""
        ''' 这个顺序是原来的index顺序 3 0 1 2(不可见) -> 0 1 2 3(不可见)
            下面代码会改变index从而实现移动'''
        for i in range(0, len(self.name)):

            if self.name[i].cur_left_Index == 1:

                self.anim1 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim1.setDuration(300)
                self.anim1.setStartValue(QRect(self.right_x, self.side_y, self.side_width, self.side_hight))
                self.anim1.setEndValue(QRect(self.center_x, 0, self.center_width, self.center_height))
                self.anim1.start()
                self.name[i].cur_left_Index = 0
                # todo 通过移动后的位置判断此时cur_right_Index应该设置为0,从而实现左移和右移都能正常实现
                self.name[i].cur_right_Index = 0
                # 图片显示在最上方
                self.name[i].raise_()
                continue

            if self.name[i].cur_left_Index == 0:

                self.anim0 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim0.setDuration(300)
                self.anim0.setStartValue(QRect(self.center_x, 0, self.center_width, self.center_height))
                self.anim0.setEndValue(QRect(self.left_x, self.side_y, self.side_width, self.side_hight))
                self.anim0.start()
                self.name[i].cur_left_Index = 3
                self.name[i].cur_right_Index = 3
                continue

            if self.name[i].cur_left_Index == 2:
                # todo 通过QGraphicsOpacityEffect设置透明度为1,从而实现label出现的效果
                op = QGraphicsOpacityEffect()
                op.setOpacity(1)
                self.name[i].setGraphicsEffect(op)
                self.anim2 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim2.setDuration(300)
                self.anim2.setStartValue(QRect(self.center_x, 0, self.side_width, self.side_hight))
                self.anim2.setEndValue(QRect(self.right_x, self.side_y, self.side_width, self.side_hight))
                self.anim2.start()
                self.name[i].cur_left_Index = 1
                self.name[i].cur_right_Index = 1
                continue

            if self.name[i].cur_left_Index == 3:
                # todo 通过QGraphicsOpacityEffect设置透明度为0,从而实现label消失的效果
                op = QGraphicsOpacityEffect()
                op.setOpacity(0)
                self.name[i].setGraphicsEffect(op)
                self.anim3 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim3.setDuration(300)
                self.anim3.setStartValue(QRect(self.left_x, self.side_y, self.side_width, self.side_hight))
                self.anim3.setEndValue(QRect(self.center_x, 0, self.side_width, self.side_hight))
                self.anim3.start()
                self.name[i].cur_left_Index = 2
                self.name[i].cur_right_Index = 2
                continue

    def init_to_right_animation(self):
        """向右移动动画"""
        ''' 顺序 3 0 1 2(不可见) -> 2 3 0 1(不可见)'''
        for i in range(0, len(self.name)):

            if self.name[i].cur_right_Index == 1:
                op = QGraphicsOpacityEffect()
                op.setOpacity(0)
                self.name[i].setGraphicsEffect(op)
                self.anim5 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim5.setDuration(300)
                self.anim5.setStartValue(QRect(self.right_x, self.side_y, self.side_width, self.side_hight))
                self.anim5.setEndValue(QRect(self.center_x, 0, self.side_width, self.side_hight))
                self.anim5.start()
                self.name[i].cur_right_Index = 2
                self.name[i].cur_left_Index = 2
                # 图片显示在最上方

                continue

            if self.name[i].cur_right_Index == 0:

                self.anim4 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim4.setDuration(300)
                self.anim4.setStartValue(QRect(self.center_x, 0, self.center_width, self.center_height))
                self.anim4.setEndValue(QRect(self.right_x, self.side_y, self.side_width, self.side_hight))
                self.anim4.start()
                self.name[i].cur_right_Index = 1
                self.name[i].cur_left_Index = 1
                continue

            if self.name[i].cur_right_Index == 2:
                op = QGraphicsOpacityEffect()
                op.setOpacity(1)
                self.name[i].setGraphicsEffect(op)
                self.anim6 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim6.setDuration(300)
                self.anim6.setStartValue(QRect(self.center_x, 0, self.side_width, self.side_hight))
                self.anim6.setEndValue(QRect(self.left_x, self.side_y, self.side_width, self.side_hight))
                self.anim6.start()
                self.name[i].cur_right_Index = 3
                self.name[i].cur_left_Index = 3
                continue

            if self.name[i].cur_right_Index == 3:

                self.anim7 = QPropertyAnimation(self.name[i], b'geometry')
                self.anim7.setDuration(300)
                self.anim7.setStartValue(QRect(self.left_x, self.side_y, self.side_width, self.side_hight))
                self.anim7.setEndValue(QRect(self.center_x, 0, self.center_width, self.center_height))
                self.anim7.start()
                self.name[i].cur_right_Index = 0
                self.name[i].cur_left_Index = 0
                self.name[i].raise_()
                continue

if __name__ == '__main__':
    app = QApplication(sys.argv)
    # app.setWindowIcon(QIcon('../images/Air Elemental.ico'))
    main = move_window()

    main.show()
    sys.exit(app.exec_())

最后是代码中包含的资源文件:

链接: https://pan.baidu.com/s/1aH_z27rV1HK3C9fy-J0pIQ?pwd=t62v 提取码: t62v 复制这段内容后打开百度网盘手机App,操作更方便哦

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
好的,下面是一个简单的PyQt5音乐播放器的实现示例: ```python import sys from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QFileDialog from PyQt5.QtCore import QUrl, Qt from PyQt5.QtMultimedia import QMediaContent, QMediaPlayer class MusicPlayer(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 300, 200) self.setWindowTitle('PyQt5 Music Player') # 播放按钮 self.playButton = QPushButton('Play', self) self.playButton.setGeometry(20, 20, 60, 25) self.playButton.clicked.connect(self.playMusic) # 停止按钮 self.stopButton = QPushButton('Stop', self) self.stopButton.setGeometry(90, 20, 60, 25) self.stopButton.clicked.connect(self.stopMusic) # 选择文件按钮 self.selectButton = QPushButton('Select', self) self.selectButton.setGeometry(160, 20, 60, 25) self.selectButton.clicked.connect(self.selectFile) # 创建MediaPlayer对象 self.mediaPlayer = QMediaPlayer(self) self.mediaPlayer.setVolume(50) self.show() def playMusic(self): if self.mediaPlayer.state() == QMediaPlayer.PlayingState: return if self.mediaPlayer.state() == QMediaPlayer.PausedState: self.mediaPlayer.play() else: self.mediaPlayer.setMedia(QMediaContent(QUrl.fromLocalFile(self.filename))) self.mediaPlayer.play() def stopMusic(self): self.mediaPlayer.stop() def selectFile(self): self.filename, _ = QFileDialog.getOpenFileName(self, 'Select Music File', '', 'Music Files (*.mp3 *.wav)') if self.filename != '': self.playButton.setEnabled(True) if __name__ == '__main__': app = QApplication(sys.argv) player = MusicPlayer() sys.exit(app.exec_()) ``` 这个示例实现了一个简单的音乐播放器,界面中有三个按钮:播放、停止、选择文件。其中,选择文件按钮使用了QFileDialog对话框来选择音乐文件。播放按钮会根据当前的播放状态进行不同的操作,停止按钮用于停止正在播放的音乐。同时,使用了QMediaPlayer类来实现音乐的播放和停止功能。 希望这个示例能够对你有所帮助!
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值